// Copyright (c) 2012 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 "content/renderer/gpu_benchmarking_extension.h"

#include <stddef.h>

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/base64.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/debug/profiler.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/macros.h"
#include "base/strings/string_number_conversions.h"
#include "build/build_config.h"
#include "cc/layers/layer.h"
#include "cc/paint/skia_paint_canvas.h"
#include "cc/trees/layer_tree_host.h"
#include "content/common/input/actions_parser.h"
#include "content/common/input/synthetic_gesture_params.h"
#include "content/common/input/synthetic_pinch_gesture_params.h"
#include "content/common/input/synthetic_pointer_action_list_params.h"
#include "content/common/input/synthetic_pointer_action_params.h"
#include "content/common/input/synthetic_smooth_drag_gesture_params.h"
#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
#include "content/common/input/synthetic_tap_gesture_params.h"
#include "content/public/common/content_switches.h"
#include "content/public/renderer/chrome_object_extensions_utils.h"
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/v8_value_converter.h"
#include "content/renderer/compositor/layer_tree_view.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_view_impl.h"
#include "content/renderer/skia_benchmarking_extension.h"
#include "gin/arguments.h"
#include "gin/handle.h"
#include "gin/object_template_builder.h"
#include "gpu/config/gpu_driver_bug_workaround_type.h"
#include "gpu/ipc/common/gpu_messages.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/public/platform/web_layer_tree_view.h"
#include "third_party/blink/public/platform/web_mouse_event.h"
#include "third_party/blink/public/web/blink.h"
#include "third_party/blink/public/web/web_image_cache.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_print_params.h"
#include "third_party/blink/public/web/web_settings.h"
#include "third_party/blink/public/web/web_view.h"
#include "third_party/skia/include/core/SkData.h"
#include "third_party/skia/include/core/SkGraphics.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "third_party/skia/include/docs/SkXPSDocument.h"
// Note that headers in third_party/skia/src are fragile.  This is
// an experimental, fragile, and diagnostic-only document type.
#include "third_party/skia/src/utils/SkMultiPictureDocument.h"
#include "ui/events/base_event_utils.h"
#include "v8/include/v8.h"

#if defined(OS_WIN) && !defined(NDEBUG)
// XpsObjectModel.h indirectly includes <wincrypt.h> which is
// incompatible with Chromium's OpenSSL. By including wincrypt_shim.h
// first, problems are avoided.
#include "base/win/wincrypt_shim.h"

#include <XpsObjectModel.h>
#include <objbase.h>
#include <wrl/client.h>
#endif

using blink::WebImageCache;
using blink::WebLocalFrame;
using blink::WebPrivatePtr;
using blink::WebSize;
using blink::WebView;

namespace content {

namespace {
class SkPictureSerializer {
 public:
  explicit SkPictureSerializer(const base::FilePath& dirpath)
      : dirpath_(dirpath), layer_id_(0) {
    // Let skia register known effect subclasses. This basically enables
    // reflection on those subclasses required for picture serialization.
    SkiaBenchmarking::Initialize();
  }

  // Recursively serializes the layer tree.
  // Each layer in the tree is serialized into a separate skp file
  // in the given directory.
  void Serialize(const cc::Layer* root_layer) {
    for (auto* layer : *root_layer->layer_tree_host()) {
      sk_sp<SkPicture> picture = layer->GetPicture();
      if (!picture)
        continue;

      // Serialize picture to file.
      // TODO(alokp): Note that for this to work Chrome needs to be launched
      // with
      // --no-sandbox command-line flag. Get rid of this limitation.
      // CRBUG: 139640.
      std::string filename =
          "layer_" + base::NumberToString(layer_id_++) + ".skp";
      std::string filepath = dirpath_.AppendASCII(filename).MaybeAsASCII();
      DCHECK(!filepath.empty());
      SkFILEWStream file(filepath.c_str());
      DCHECK(file.isValid());

      auto data = picture->serialize();
      file.write(data->data(), data->size());
      file.fsync();
    }
  }

 private:
  base::FilePath dirpath_;
  int layer_id_;
};

template <typename T>
bool GetArg(gin::Arguments* args, T* value) {
  if (!args->GetNext(value)) {
    args->ThrowError();
    return false;
  }
  return true;
}

template <>
bool GetArg(gin::Arguments* args, int* value) {
  float number;
  bool ret = GetArg(args, &number);
  *value = number;
  return ret;
}

template <typename T>
bool GetOptionalArg(gin::Arguments* args, T* value) {
  if (args->PeekNext().IsEmpty())
    return true;
  if (args->PeekNext()->IsUndefined()) {
    args->Skip();
    return true;
  }
  return GetArg(args, value);
}

class CallbackAndContext : public base::RefCounted<CallbackAndContext> {
 public:
  CallbackAndContext(v8::Isolate* isolate,
                     v8::Local<v8::Function> callback,
                     v8::Local<v8::Context> context)
      : isolate_(isolate) {
    callback_.Reset(isolate_, callback);
    context_.Reset(isolate_, context);
  }

  v8::Isolate* isolate() { return isolate_; }

  v8::Local<v8::Function> GetCallback() {
    return v8::Local<v8::Function>::New(isolate_, callback_);
  }

  v8::Local<v8::Context> GetContext() {
    return v8::Local<v8::Context>::New(isolate_, context_);
  }

 private:
  friend class base::RefCounted<CallbackAndContext>;

  virtual ~CallbackAndContext() {
    callback_.Reset();
    context_.Reset();
  }

  v8::Isolate* isolate_;
  v8::Persistent<v8::Function> callback_;
  v8::Persistent<v8::Context> context_;
  DISALLOW_COPY_AND_ASSIGN(CallbackAndContext);
};

class GpuBenchmarkingContext {
 public:
  GpuBenchmarkingContext() = default;

  bool Init(bool init_compositor) {
    web_frame_ = WebLocalFrame::FrameForCurrentContext();
    if (!web_frame_)
      return false;

    web_view_ = web_frame_->View();
    if (!web_view_) {
      web_frame_ = nullptr;
      return false;
    }

    render_view_impl_ = RenderViewImpl::FromWebView(web_view_);
    if (!render_view_impl_) {
      web_frame_ = nullptr;
      web_view_ = nullptr;
      return false;
    }

    if (!init_compositor)
      return true;

    layer_tree_view_ = render_view_impl_->GetWidget()->layer_tree_view();
    if (!layer_tree_view_) {
      web_frame_ = nullptr;
      web_view_ = nullptr;
      render_view_impl_ = nullptr;
      return false;
    }

    return true;
  }

  WebLocalFrame* web_frame() const {
    DCHECK(web_frame_ != nullptr);
    return web_frame_;
  }
  WebView* web_view() const {
    DCHECK(web_view_ != nullptr);
    return web_view_;
  }
  RenderViewImpl* render_view_impl() const {
    DCHECK(render_view_impl_ != nullptr);
    return render_view_impl_;
  }
  LayerTreeView* layer_tree_view() const {
    DCHECK(layer_tree_view_ != nullptr);
    return layer_tree_view_;
  }

 private:
  WebLocalFrame* web_frame_ = nullptr;
  WebView* web_view_ = nullptr;
  RenderViewImpl* render_view_impl_ = nullptr;
  LayerTreeView* layer_tree_view_ = nullptr;

  DISALLOW_COPY_AND_ASSIGN(GpuBenchmarkingContext);
};

void OnMicroBenchmarkCompleted(CallbackAndContext* callback_and_context,
                               std::unique_ptr<base::Value> result) {
  v8::Isolate* isolate = callback_and_context->isolate();
  v8::HandleScope scope(isolate);
  v8::Local<v8::Context> context = callback_and_context->GetContext();
  v8::Context::Scope context_scope(context);
  WebLocalFrame* frame = WebLocalFrame::FrameForContext(context);
  if (frame) {
    v8::Local<v8::Value> value =
        V8ValueConverter::Create()->ToV8Value(result.get(), context);
    v8::Local<v8::Value> argv[] = {value};

    frame->CallFunctionEvenIfScriptDisabled(callback_and_context->GetCallback(),
                                            v8::Object::New(isolate), 1, argv);
  }
}

void RunCallbackHelper(CallbackAndContext* callback_and_context) {
  v8::Isolate* isolate = callback_and_context->isolate();
  v8::HandleScope scope(isolate);
  v8::Local<v8::Context> context = callback_and_context->GetContext();
  v8::Context::Scope context_scope(context);
  v8::Local<v8::Function> callback = callback_and_context->GetCallback();
  WebLocalFrame* frame = WebLocalFrame::FrameForContext(context);
  if (frame && !callback.IsEmpty()) {
    frame->CallFunctionEvenIfScriptDisabled(callback, v8::Object::New(isolate),
                                            0, nullptr);
  }
}

void OnSyntheticGestureCompleted(CallbackAndContext* callback_and_context) {
  RunCallbackHelper(callback_and_context);
}

bool ThrowIfPointOutOfBounds(GpuBenchmarkingContext* context,
                             gin::Arguments* args,
                             const gfx::Point& point,
                             const std::string& message) {
  gfx::Rect rect = context->render_view_impl()->GetWidget()->ViewRect();
  rect -= rect.OffsetFromOrigin();

  // If the bounds are not available here, as is the case with an OOPIF,
  // for now, we will forgo the renderer-side bounds check.
  if (rect.IsEmpty())
    return false;

  if (!rect.Contains(point)) {
    args->ThrowTypeError(message);
    return true;
  }

  return false;
}

bool BeginSmoothScroll(GpuBenchmarkingContext* context,
                       gin::Arguments* args,
                       mojom::InputInjectorPtr& injector,
                       float pixels_to_scroll,
                       v8::Local<v8::Function> callback,
                       int gesture_source_type,
                       const std::string& direction,
                       float speed_in_pixels_s,
                       bool prevent_fling,
                       float start_x,
                       float start_y,
                       float fling_velocity,
                       bool precise_scrolling_deltas,
                       bool scroll_by_page,
                       bool cursor_visible) {
  if (ThrowIfPointOutOfBounds(context, args, gfx::Point(start_x, start_y),
                              "Start point not in bounds")) {
    return false;
  }

  if (gesture_source_type == SyntheticGestureParams::MOUSE_INPUT) {
    // Ensure the mouse is visible and move to start position, in case it will
    // trigger any hover or mousemove effects.
    context->web_view()->SetIsActive(true);
    blink::WebMouseEvent mouseMove(blink::WebInputEvent::kMouseMove,
                                   blink::WebInputEvent::kNoModifiers,
                                   ui::EventTimeForNow());
    mouseMove.SetPositionInWidget(start_x, start_y);
    context->web_view()->MainFrameWidget()->HandleInputEvent(
        blink::WebCoalescedInputEvent(mouseMove));
    context->web_view()->MainFrameWidget()->SetCursorVisibilityState(
        cursor_visible);
  }

  scoped_refptr<CallbackAndContext> callback_and_context =
      new CallbackAndContext(args->isolate(), callback,
                             context->web_frame()->MainWorldScriptContext());

  SyntheticSmoothScrollGestureParams gesture_params;

  if (gesture_source_type < 0 ||
      gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
    return false;
  }
  gesture_params.gesture_source_type =
      static_cast<SyntheticGestureParams::GestureSourceType>(
          gesture_source_type);

  gesture_params.speed_in_pixels_s = speed_in_pixels_s;
  gesture_params.prevent_fling = prevent_fling;
  gesture_params.precise_scrolling_deltas = precise_scrolling_deltas;
  gesture_params.scroll_by_page = scroll_by_page;

  gesture_params.anchor.SetPoint(start_x, start_y);

  DCHECK(gesture_source_type != SyntheticGestureParams::TOUCH_INPUT ||
         fling_velocity == 0);
  float distance_length = pixels_to_scroll;
  gfx::Vector2dF distance;
  if (direction == "down") {
    distance.set_y(-distance_length);
    gesture_params.fling_velocity_y = fling_velocity;
  } else if (direction == "up") {
    distance.set_y(distance_length);
    gesture_params.fling_velocity_y = -fling_velocity;
  } else if (direction == "right") {
    distance.set_x(-distance_length);
    gesture_params.fling_velocity_x = fling_velocity;
  } else if (direction == "left") {
    distance.set_x(distance_length);
    gesture_params.fling_velocity_x = -fling_velocity;
  } else if (direction == "upleft") {
    distance.set_y(distance_length);
    distance.set_x(distance_length);
    gesture_params.fling_velocity_x = -fling_velocity;
    gesture_params.fling_velocity_y = -fling_velocity;
  } else if (direction == "upright") {
    distance.set_y(distance_length);
    distance.set_x(-distance_length);
    gesture_params.fling_velocity_x = fling_velocity;
    gesture_params.fling_velocity_y = -fling_velocity;
  } else if (direction == "downleft") {
    distance.set_y(-distance_length);
    distance.set_x(distance_length);
    gesture_params.fling_velocity_x = -fling_velocity;
    gesture_params.fling_velocity_y = fling_velocity;
  } else if (direction == "downright") {
    distance.set_y(-distance_length);
    distance.set_x(-distance_length);
    gesture_params.fling_velocity_x = fling_velocity;
    gesture_params.fling_velocity_y = fling_velocity;
  } else {
    return false;
  }
  gesture_params.distances.push_back(distance);

  injector->QueueSyntheticSmoothScroll(
      gesture_params, base::BindOnce(&OnSyntheticGestureCompleted,
                                     base::RetainedRef(callback_and_context)));

  return true;
}

bool BeginSmoothDrag(GpuBenchmarkingContext* context,
                     gin::Arguments* args,
                     mojom::InputInjectorPtr& injector,
                     float start_x,
                     float start_y,
                     float end_x,
                     float end_y,
                     v8::Local<v8::Function> callback,
                     int gesture_source_type,
                     float speed_in_pixels_s) {
  if (ThrowIfPointOutOfBounds(context, args, gfx::Point(start_x, start_y),
                              "Start point not in bounds")) {
    return false;
  }

  scoped_refptr<CallbackAndContext> callback_and_context =
      new CallbackAndContext(args->isolate(), callback,
                             context->web_frame()->MainWorldScriptContext());

  SyntheticSmoothDragGestureParams gesture_params;

  gesture_params.start_point.SetPoint(start_x, start_y);
  gfx::PointF end_point(end_x, end_y);
  gfx::Vector2dF distance = end_point - gesture_params.start_point;
  gesture_params.distances.push_back(distance);
  gesture_params.speed_in_pixels_s = speed_in_pixels_s;
  gesture_params.gesture_source_type =
      static_cast<SyntheticGestureParams::GestureSourceType>(
          gesture_source_type);

  injector->QueueSyntheticSmoothDrag(
      gesture_params, base::BindOnce(&OnSyntheticGestureCompleted,
                                     base::RetainedRef(callback_and_context)));

  return true;
}

static void PrintDocument(blink::WebLocalFrame* frame, SkDocument* doc) {
  const float kPageWidth = 612.0f;   // 8.5 inch
  const float kPageHeight = 792.0f;  // 11 inch
  const float kMarginTop = 29.0f;    // 0.40 inch
  const float kMarginLeft = 29.0f;   // 0.40 inch
  const int kContentWidth = 555;     // 7.71 inch
  const int kContentHeight = 735;    // 10.21 inch
  blink::WebPrintParams params(blink::WebSize(kContentWidth, kContentHeight));
  params.printer_dpi = 300;
  int page_count = frame->PrintBegin(params);
  for (int i = 0; i < page_count; ++i) {
    SkCanvas* sk_canvas = doc->beginPage(kPageWidth, kPageHeight);
    cc::SkiaPaintCanvas canvas(sk_canvas);
    cc::PaintCanvasAutoRestore auto_restore(&canvas, true);
    canvas.translate(kMarginLeft, kMarginTop);

#if defined(OS_WIN) || defined(OS_MACOSX)
    float page_shrink = frame->GetPrintPageShrink(i);
    DCHECK_GT(page_shrink, 0);
    canvas.scale(page_shrink, page_shrink);
#endif

    frame->PrintPage(i, &canvas);
  }
  frame->PrintEnd();
}

static void PrintDocumentTofile(v8::Isolate* isolate,
                                const std::string& filename,
                                sk_sp<SkDocument> (*make_doc)(SkWStream*)) {
  GpuBenchmarkingContext context;
  if (!context.Init(true))
    return;

  base::FilePath path = base::FilePath::FromUTF8Unsafe(filename);
  if (!base::PathIsWritable(path.DirName())) {
    std::string msg("Path is not writable: ");
    msg.append(path.DirName().MaybeAsASCII());
    isolate->ThrowException(v8::Exception::Error(
        v8::String::NewFromUtf8(isolate, msg.c_str(),
                                v8::NewStringType::kNormal, msg.length())
            .ToLocalChecked()));
    return;
  }
  SkFILEWStream wStream(path.MaybeAsASCII().c_str());
  sk_sp<SkDocument> doc = make_doc(&wStream);
  if (doc) {
    context.web_frame()->View()->GetSettings()->SetShouldPrintBackgrounds(true);
    PrintDocument(context.web_frame(), doc.get());
    doc->close();
  }
}

void OnSwapCompletedHelper(CallbackAndContext* callback_and_context,
                           blink::WebLayerTreeView::SwapResult,
                           base::TimeTicks) {
  RunCallbackHelper(callback_and_context);
}

// This function is only used for correctness testing of this experimental
// feature; no need for it in release builds.
// Also note:  You must execute Chrome with `--no-sandbox` and
// `--enable-gpu-benchmarking` for this to work.
#if defined(OS_WIN) && !defined(NDEBUG)
static sk_sp<SkDocument> MakeXPSDocument(SkWStream* s) {
  // I am not sure why this hasn't been initialized yet.
  (void)CoInitializeEx(nullptr,
                       COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
  // In non-sandboxed mode, we will need to create and hold on to the
  // factory before entering the sandbox.
  Microsoft::WRL::ComPtr<IXpsOMObjectFactory> factory;
  HRESULT hr = ::CoCreateInstance(CLSID_XpsOMObjectFactory, nullptr,
                                  CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&factory));
  if (FAILED(hr) || !factory) {
    LOG(ERROR) << "CoCreateInstance(CLSID_XpsOMObjectFactory, ...) failed:"
               << logging::SystemErrorCodeToString(hr);
  }
  return SkXPS::MakeDocument(s, factory.Get());
}
#endif
}  // namespace

gin::WrapperInfo GpuBenchmarking::kWrapperInfo = {gin::kEmbedderNativeGin};

// static
void GpuBenchmarking::Install(RenderFrameImpl* frame) {
  v8::Isolate* isolate = blink::MainThreadIsolate();
  v8::HandleScope handle_scope(isolate);
  v8::Local<v8::Context> context =
      frame->GetWebFrame()->MainWorldScriptContext();
  if (context.IsEmpty())
    return;

  v8::Context::Scope context_scope(context);

  gin::Handle<GpuBenchmarking> controller =
      gin::CreateHandle(isolate, new GpuBenchmarking(frame));
  if (controller.IsEmpty())
    return;

  v8::Local<v8::Object> chrome = GetOrCreateChromeObject(isolate, context);
  chrome->Set(gin::StringToV8(isolate, "gpuBenchmarking"), controller.ToV8());
}

GpuBenchmarking::GpuBenchmarking(RenderFrameImpl* frame)
    : render_frame_(frame) {}

GpuBenchmarking::~GpuBenchmarking() {}

void GpuBenchmarking::EnsureRemoteInterface() {
  if (!input_injector_) {
    render_frame_->GetRemoteInterfaces()->GetInterface(mojo::MakeRequest(
        &input_injector_,
        render_frame_->GetTaskRunner(blink::TaskType::kInternalDefault)));
  }
}

gin::ObjectTemplateBuilder GpuBenchmarking::GetObjectTemplateBuilder(
    v8::Isolate* isolate) {
  return gin::Wrappable<GpuBenchmarking>::GetObjectTemplateBuilder(isolate)
      .SetMethod("setNeedsDisplayOnAllLayers",
                 &GpuBenchmarking::SetNeedsDisplayOnAllLayers)
      .SetMethod("setRasterizeOnlyVisibleContent",
                 &GpuBenchmarking::SetRasterizeOnlyVisibleContent)
      .SetMethod("printToSkPicture", &GpuBenchmarking::PrintToSkPicture)
      .SetMethod("printPagesToSkPictures",
                 &GpuBenchmarking::PrintPagesToSkPictures)
      .SetMethod("printPagesToXPS", &GpuBenchmarking::PrintPagesToXPS)
      .SetValue("DEFAULT_INPUT",
                static_cast<int>(SyntheticGestureParams::DEFAULT_INPUT))
      .SetValue("TOUCH_INPUT",
                static_cast<int>(SyntheticGestureParams::TOUCH_INPUT))
      .SetValue("MOUSE_INPUT",
                static_cast<int>(SyntheticGestureParams::MOUSE_INPUT))
      .SetValue("TOUCHPAD_INPUT",
                static_cast<int>(SyntheticGestureParams::TOUCHPAD_INPUT))
      .SetValue("PEN_INPUT",
                static_cast<int>(SyntheticGestureParams::PEN_INPUT))
      .SetMethod("gestureSourceTypeSupported",
                 &GpuBenchmarking::GestureSourceTypeSupported)
      .SetMethod("smoothScrollBy", &GpuBenchmarking::SmoothScrollBy)
      .SetMethod("smoothDrag", &GpuBenchmarking::SmoothDrag)
      .SetMethod("swipe", &GpuBenchmarking::Swipe)
      .SetMethod("scrollBounce", &GpuBenchmarking::ScrollBounce)
      .SetMethod("pinchBy", &GpuBenchmarking::PinchBy)
      .SetMethod("pageScaleFactor", &GpuBenchmarking::PageScaleFactor)
      .SetMethod("setPageScaleFactor", &GpuBenchmarking::SetPageScaleFactor)
      .SetMethod("setBrowserControlsShown",
                 &GpuBenchmarking::SetBrowserControlsShown)
      .SetMethod("tap", &GpuBenchmarking::Tap)
      .SetMethod("pointerActionSequence",
                 &GpuBenchmarking::PointerActionSequence)
      .SetMethod("visualViewportX", &GpuBenchmarking::VisualViewportX)
      .SetMethod("visualViewportY", &GpuBenchmarking::VisualViewportY)
      .SetMethod("visualViewportHeight", &GpuBenchmarking::VisualViewportHeight)
      .SetMethod("visualViewportWidth", &GpuBenchmarking::VisualViewportWidth)
      .SetMethod("clearImageCache", &GpuBenchmarking::ClearImageCache)
      .SetMethod("runMicroBenchmark", &GpuBenchmarking::RunMicroBenchmark)
      .SetMethod("sendMessageToMicroBenchmark",
                 &GpuBenchmarking::SendMessageToMicroBenchmark)
      .SetMethod("hasGpuChannel", &GpuBenchmarking::HasGpuChannel)
      .SetMethod("hasGpuProcess", &GpuBenchmarking::HasGpuProcess)
      .SetMethod("crashGpuProcess", &GpuBenchmarking::CrashGpuProcess)
      .SetMethod("getGpuDriverBugWorkarounds",
                 &GpuBenchmarking::GetGpuDriverBugWorkarounds)
      .SetMethod("startProfiling", &GpuBenchmarking::StartProfiling)
      .SetMethod("stopProfiling", &GpuBenchmarking::StopProfiling)
      .SetMethod("freeze", &GpuBenchmarking::Freeze)
      .SetMethod("addSwapCompletionEventListener",
                 &GpuBenchmarking::AddSwapCompletionEventListener);
}

void GpuBenchmarking::SetNeedsDisplayOnAllLayers() {
  GpuBenchmarkingContext context;
  if (!context.Init(true))
    return;

  context.layer_tree_view()->SetNeedsDisplayOnAllLayers();
}

void GpuBenchmarking::SetRasterizeOnlyVisibleContent() {
  GpuBenchmarkingContext context;
  if (!context.Init(true))
    return;

  context.layer_tree_view()->SetRasterizeOnlyVisibleContent();
}

namespace {
sk_sp<SkDocument> make_multipicturedocument(SkWStream* stream) {
  return SkMakeMultiPictureDocument(stream);
}
}  // namespace
void GpuBenchmarking::PrintPagesToSkPictures(v8::Isolate* isolate,
                                             const std::string& filename) {
  PrintDocumentTofile(isolate, filename, &make_multipicturedocument);
}

void GpuBenchmarking::PrintPagesToXPS(v8::Isolate* isolate,
                                      const std::string& filename) {
#if defined(OS_WIN) && !defined(NDEBUG)
  PrintDocumentTofile(isolate, filename, &MakeXPSDocument);
#else
  std::string msg("PrintPagesToXPS is unsupported.");
  isolate->ThrowException(v8::Exception::Error(
      v8::String::NewFromUtf8(isolate, msg.c_str(), v8::NewStringType::kNormal,
                              msg.length())
          .ToLocalChecked()));
#endif
}

void GpuBenchmarking::PrintToSkPicture(v8::Isolate* isolate,
                                       const std::string& dirname) {
  GpuBenchmarkingContext context;
  if (!context.Init(true))
    return;

  const cc::Layer* root_layer = context.layer_tree_view()->GetRootLayer();
  if (!root_layer)
    return;

  base::FilePath dirpath = base::FilePath::FromUTF8Unsafe(dirname);
  if (!base::CreateDirectory(dirpath) || !base::PathIsWritable(dirpath)) {
    std::string msg("Path is not writable: ");
    msg.append(dirpath.MaybeAsASCII());
    isolate->ThrowException(v8::Exception::Error(
        v8::String::NewFromUtf8(isolate, msg.c_str(),
                                v8::NewStringType::kNormal, msg.length())
            .ToLocalChecked()));
    return;
  }

  SkPictureSerializer serializer(dirpath);
  serializer.Serialize(root_layer);
}

bool GpuBenchmarking::GestureSourceTypeSupported(int gesture_source_type) {
  if (gesture_source_type < 0 ||
      gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
    return false;
  }

  return SyntheticGestureParams::IsGestureSourceTypeSupported(
      static_cast<SyntheticGestureParams::GestureSourceType>(
          gesture_source_type));
}

bool GpuBenchmarking::SmoothScrollBy(gin::Arguments* args) {
  GpuBenchmarkingContext context;
  if (!context.Init(true))
    return false;

  blink::WebRect rect = context.render_view_impl()->GetWidget()->ViewRect();

  float pixels_to_scroll = 0;
  v8::Local<v8::Function> callback;
  float start_x = rect.width / 2;
  float start_y = rect.height / 2;
  int gesture_source_type = SyntheticGestureParams::DEFAULT_INPUT;
  std::string direction = "down";
  float speed_in_pixels_s = 800;
  bool precise_scrolling_deltas = true;
  bool scroll_by_page = false;
  bool cursor_visible = true;

  if (!GetOptionalArg(args, &pixels_to_scroll) ||
      !GetOptionalArg(args, &callback) || !GetOptionalArg(args, &start_x) ||
      !GetOptionalArg(args, &start_y) ||
      !GetOptionalArg(args, &gesture_source_type) ||
      !GetOptionalArg(args, &direction) ||
      !GetOptionalArg(args, &speed_in_pixels_s) ||
      !GetOptionalArg(args, &precise_scrolling_deltas) ||
      !GetOptionalArg(args, &scroll_by_page) ||
      !GetOptionalArg(args, &cursor_visible)) {
    return false;
  }

  // For all touch inputs, always scroll by precise deltas.
  DCHECK(gesture_source_type != SyntheticGestureParams::TOUCH_INPUT ||
         precise_scrolling_deltas);
  // Scroll by page only for mouse inputs.
  DCHECK(!scroll_by_page ||
         gesture_source_type == SyntheticGestureParams::MOUSE_INPUT);

  EnsureRemoteInterface();
  return BeginSmoothScroll(
      &context, args, input_injector_, pixels_to_scroll, callback,
      gesture_source_type, direction, speed_in_pixels_s, true, start_x, start_y,
      0, precise_scrolling_deltas, scroll_by_page, cursor_visible);
}

bool GpuBenchmarking::SmoothDrag(gin::Arguments* args) {
  GpuBenchmarkingContext context;
  if (!context.Init(true))
    return false;

  float start_x;
  float start_y;
  float end_x;
  float end_y;
  v8::Local<v8::Function> callback;
  int gesture_source_type = SyntheticGestureParams::DEFAULT_INPUT;
  float speed_in_pixels_s = 800;

  if (!GetArg(args, &start_x) || !GetArg(args, &start_y) ||
      !GetArg(args, &end_x) || !GetArg(args, &end_y) ||
      !GetOptionalArg(args, &callback) ||
      !GetOptionalArg(args, &gesture_source_type) ||
      !GetOptionalArg(args, &speed_in_pixels_s)) {
    return false;
  }

  EnsureRemoteInterface();
  return BeginSmoothDrag(&context, args, input_injector_, start_x, start_y,
                         end_x, end_y, callback, gesture_source_type,
                         speed_in_pixels_s);
}

bool GpuBenchmarking::Swipe(gin::Arguments* args) {
  GpuBenchmarkingContext context;
  if (!context.Init(true))
    return false;

  blink::WebRect rect = context.render_view_impl()->GetWidget()->ViewRect();

  std::string direction = "up";
  float pixels_to_scroll = 0;
  v8::Local<v8::Function> callback;
  float start_x = rect.width / 2;
  float start_y = rect.height / 2;
  float speed_in_pixels_s = 800;
  float fling_velocity = 0;
  int gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;

  if (!GetOptionalArg(args, &direction) ||
      !GetOptionalArg(args, &pixels_to_scroll) ||
      !GetOptionalArg(args, &callback) || !GetOptionalArg(args, &start_x) ||
      !GetOptionalArg(args, &start_y) ||
      !GetOptionalArg(args, &speed_in_pixels_s) ||
      !GetOptionalArg(args, &fling_velocity) ||
      !GetOptionalArg(args, &gesture_source_type)) {
    return false;
  }

  // For touchpad swipe, we should be given a fling velocity, but it is not
  // needed for touchscreen swipe, because we will calculate the velocity in
  // our code.
  if (gesture_source_type == SyntheticGestureParams::TOUCHPAD_INPUT &&
      fling_velocity == 0)
    fling_velocity = 1000;

  EnsureRemoteInterface();
  return BeginSmoothScroll(
      &context, args, input_injector_, -pixels_to_scroll, callback,
      gesture_source_type, direction, speed_in_pixels_s, false, start_x,
      start_y, fling_velocity, true /* precise_scrolling_deltas */,
      false /* scroll_by_page */, true /* cursor_visible */);
}

bool GpuBenchmarking::ScrollBounce(gin::Arguments* args) {
  GpuBenchmarkingContext context;
  if (!context.Init(false))
    return false;

  blink::WebRect content_rect =
      context.render_view_impl()->GetWidget()->ViewRect();

  std::string direction = "down";
  float distance_length = 0;
  float overscroll_length = 0;
  int repeat_count = 1;
  v8::Local<v8::Function> callback;
  float start_x = content_rect.width / 2;
  float start_y = content_rect.height / 2;
  float speed_in_pixels_s = 800;

  if (!GetOptionalArg(args, &direction) ||
      !GetOptionalArg(args, &distance_length) ||
      !GetOptionalArg(args, &overscroll_length) ||
      !GetOptionalArg(args, &repeat_count) ||
      !GetOptionalArg(args, &callback) || !GetOptionalArg(args, &start_x) ||
      !GetOptionalArg(args, &start_y) ||
      !GetOptionalArg(args, &speed_in_pixels_s)) {
    return false;
  }

  if (ThrowIfPointOutOfBounds(&context, args, gfx::Point(start_x, start_y),
                              "Start point not in bounds")) {
    return false;
  }

  scoped_refptr<CallbackAndContext> callback_and_context =
      new CallbackAndContext(args->isolate(), callback,
                             context.web_frame()->MainWorldScriptContext());

  SyntheticSmoothScrollGestureParams gesture_params;

  gesture_params.speed_in_pixels_s = speed_in_pixels_s;

  gesture_params.anchor.SetPoint(start_x, start_y);

  gfx::Vector2dF distance;
  gfx::Vector2dF overscroll;
  if (direction == "down") {
    distance.set_y(-distance_length);
    overscroll.set_y(overscroll_length);
  } else if (direction == "up") {
    distance.set_y(distance_length);
    overscroll.set_y(-overscroll_length);
  } else if (direction == "right") {
    distance.set_x(-distance_length);
    overscroll.set_x(overscroll_length);
  } else if (direction == "left") {
    distance.set_x(distance_length);
    overscroll.set_x(-overscroll_length);
  } else {
    return false;
  }

  for (int i = 0; i < repeat_count; i++) {
    gesture_params.distances.push_back(distance);
    gesture_params.distances.push_back(-distance + overscroll);
  }
  EnsureRemoteInterface();
  input_injector_->QueueSyntheticSmoothScroll(
      gesture_params, base::BindOnce(&OnSyntheticGestureCompleted,
                                     base::RetainedRef(callback_and_context)));

  return true;
}

bool GpuBenchmarking::PinchBy(gin::Arguments* args) {
  GpuBenchmarkingContext context;
  if (!context.Init(false))
    return false;

  float scale_factor;
  float anchor_x;
  float anchor_y;
  v8::Local<v8::Function> callback;
  float relative_pointer_speed_in_pixels_s = 800;
  int gesture_source_type = SyntheticGestureParams::DEFAULT_INPUT;

  if (!GetArg(args, &scale_factor) || !GetArg(args, &anchor_x) ||
      !GetArg(args, &anchor_y) || !GetOptionalArg(args, &callback) ||
      !GetOptionalArg(args, &relative_pointer_speed_in_pixels_s) ||
      !GetOptionalArg(args, &gesture_source_type)) {
    return false;
  }

  if (ThrowIfPointOutOfBounds(&context, args, gfx::Point(anchor_x, anchor_y),
                              "Anchor point not in bounds")) {
    return false;
  }

  SyntheticPinchGestureParams gesture_params;

  gesture_params.scale_factor = scale_factor;
  gesture_params.anchor.SetPoint(anchor_x, anchor_y);
  gesture_params.relative_pointer_speed_in_pixels_s =
      relative_pointer_speed_in_pixels_s;

  if (gesture_source_type < 0 ||
      gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
    args->ThrowTypeError("Unknown gesture source type");
    return false;
  }

  gesture_params.gesture_source_type =
      static_cast<SyntheticGestureParams::GestureSourceType>(
          gesture_source_type);

  switch (gesture_params.gesture_source_type) {
    case SyntheticGestureParams::DEFAULT_INPUT:
    case SyntheticGestureParams::TOUCH_INPUT:
    case SyntheticGestureParams::MOUSE_INPUT:
      break;
    case SyntheticGestureParams::PEN_INPUT:
      args->ThrowTypeError(
          "Gesture is not implemented for the given source type");
      return false;
  }

  scoped_refptr<CallbackAndContext> callback_and_context =
      new CallbackAndContext(args->isolate(), callback,
                             context.web_frame()->MainWorldScriptContext());
  EnsureRemoteInterface();
  input_injector_->QueueSyntheticPinch(
      gesture_params, base::BindOnce(&OnSyntheticGestureCompleted,
                                     base::RetainedRef(callback_and_context)));

  return true;
}

float GpuBenchmarking::PageScaleFactor() {
  GpuBenchmarkingContext context;
  if (!context.Init(false))
    return 0.0;
  return context.web_view()->PageScaleFactor();
}

void GpuBenchmarking::SetPageScaleFactor(float scale) {
  GpuBenchmarkingContext context;
  if (!context.Init(false))
    return;
  context.web_view()->SetPageScaleFactor(scale);
}

void GpuBenchmarking::SetBrowserControlsShown(bool show) {
  GpuBenchmarkingContext context;
  if (!context.Init(true))
    return;
  context.layer_tree_view()->UpdateBrowserControlsState(
      cc::BrowserControlsState::kBoth,
      show ? cc::BrowserControlsState::kShown
           : cc::BrowserControlsState::kHidden,
      false);
}

float GpuBenchmarking::VisualViewportY() {
  GpuBenchmarkingContext context;
  if (!context.Init(false))
    return 0.0;
  float y = context.web_view()->VisualViewportOffset().y;
  blink::WebRect rect(0, y, 0, 0);
  context.render_view_impl()->WidgetClient()->ConvertViewportToWindow(&rect);
  return rect.y;
}

float GpuBenchmarking::VisualViewportX() {
  GpuBenchmarkingContext context;
  if (!context.Init(false))
    return 0.0;
  float x = context.web_view()->VisualViewportOffset().x;
  blink::WebRect rect(x, 0, 0, 0);
  context.render_view_impl()->WidgetClient()->ConvertViewportToWindow(&rect);
  return rect.x;
}

float GpuBenchmarking::VisualViewportHeight() {
  GpuBenchmarkingContext context;
  if (!context.Init(false))
    return 0.0;
  float height = context.web_view()->VisualViewportSize().height;
  blink::WebRect rect(0, 0, 0, height);
  context.render_view_impl()->WidgetClient()->ConvertViewportToWindow(&rect);
  return rect.height;
}

float GpuBenchmarking::VisualViewportWidth() {
  GpuBenchmarkingContext context;
  if (!context.Init(false))
    return 0.0;
  float width = context.web_view()->VisualViewportSize().width;
  blink::WebRect rect(0, 0, width, 0);
  context.render_view_impl()->WidgetClient()->ConvertViewportToWindow(&rect);
  return rect.width;
}

bool GpuBenchmarking::Tap(gin::Arguments* args) {
  GpuBenchmarkingContext context;
  if (!context.Init(false))
    return false;

  float position_x;
  float position_y;
  v8::Local<v8::Function> callback;
  int duration_ms = 50;
  int gesture_source_type = SyntheticGestureParams::DEFAULT_INPUT;

  if (!GetArg(args, &position_x) || !GetArg(args, &position_y) ||
      !GetOptionalArg(args, &callback) || !GetOptionalArg(args, &duration_ms) ||
      !GetOptionalArg(args, &gesture_source_type)) {
    return false;
  }

  if (ThrowIfPointOutOfBounds(&context, args,
                              gfx::Point(position_x, position_y),
                              "Start point not in bounds")) {
    return false;
  }

  SyntheticTapGestureParams gesture_params;

  gesture_params.position.SetPoint(position_x, position_y);
  gesture_params.duration_ms = duration_ms;

  if (gesture_source_type < 0 ||
      gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
    return false;
  }
  gesture_params.gesture_source_type =
      static_cast<SyntheticGestureParams::GestureSourceType>(
          gesture_source_type);

  scoped_refptr<CallbackAndContext> callback_and_context =
      new CallbackAndContext(args->isolate(), callback,
                             context.web_frame()->MainWorldScriptContext());
  EnsureRemoteInterface();
  input_injector_->QueueSyntheticTap(
      gesture_params, base::BindOnce(&OnSyntheticGestureCompleted,
                                     base::RetainedRef(callback_and_context)));

  return true;
}

bool GpuBenchmarking::PointerActionSequence(gin::Arguments* args) {
  GpuBenchmarkingContext context;
  if (!context.Init(false))
    return false;

  v8::Local<v8::Function> callback;

  v8::Local<v8::Object> obj;
  if (!args->GetNext(&obj)) {
    args->ThrowError();
    return false;
  }

  v8::Local<v8::Context> v8_context =
      context.web_frame()->MainWorldScriptContext();
  std::unique_ptr<base::Value> value =
      V8ValueConverter::Create()->FromV8Value(obj, v8_context);

  // Get all the pointer actions from the user input and wrap them into a
  // SyntheticPointerActionListParams object.
  ActionsParser actions_parser(value.get());
  if (!actions_parser.ParsePointerActionSequence()) {
    // TODO(dtapuska): Throw an error here, some web tests start
    // failing when this is done though.
    // args->ThrowTypeError(actions_parser.error_message());
    return false;
  }

  if (!GetOptionalArg(args, &callback)) {
    args->ThrowError();
    return false;
  }

  // At the end, we will send a 'FINISH' action and need a callback.
  scoped_refptr<CallbackAndContext> callback_and_context =
      new CallbackAndContext(args->isolate(), callback,
                             context.web_frame()->MainWorldScriptContext());
  EnsureRemoteInterface();
  input_injector_->QueueSyntheticPointerAction(
      actions_parser.gesture_params(),
      base::BindOnce(&OnSyntheticGestureCompleted,
                     base::RetainedRef(callback_and_context)));
  return true;
}

void GpuBenchmarking::ClearImageCache() {
  WebImageCache::Clear();
}

int GpuBenchmarking::RunMicroBenchmark(gin::Arguments* args) {
  GpuBenchmarkingContext context;
  if (!context.Init(true))
    return 0;

  std::string name;
  v8::Local<v8::Function> callback;
  v8::Local<v8::Object> arguments;

  if (!GetArg(args, &name) || !GetArg(args, &callback) ||
      !GetOptionalArg(args, &arguments)) {
    return 0;
  }

  scoped_refptr<CallbackAndContext> callback_and_context =
      new CallbackAndContext(args->isolate(), callback,
                             context.web_frame()->MainWorldScriptContext());

  v8::Local<v8::Context> v8_context = callback_and_context->GetContext();
  std::unique_ptr<base::Value> value =
      V8ValueConverter::Create()->FromV8Value(arguments, v8_context);

  return context.layer_tree_view()->ScheduleMicroBenchmark(
      name, std::move(value),
      base::BindOnce(&OnMicroBenchmarkCompleted,
                     base::RetainedRef(callback_and_context)));
}

bool GpuBenchmarking::SendMessageToMicroBenchmark(
    int id,
    v8::Local<v8::Object> message) {
  GpuBenchmarkingContext context;
  if (!context.Init(true))
    return false;

  v8::Local<v8::Context> v8_context =
      context.web_frame()->MainWorldScriptContext();
  std::unique_ptr<base::Value> value =
      V8ValueConverter::Create()->FromV8Value(message, v8_context);

  return context.layer_tree_view()->SendMessageToMicroBenchmark(
      id, std::move(value));
}

bool GpuBenchmarking::HasGpuChannel() {
  gpu::GpuChannelHost* gpu_channel =
      RenderThreadImpl::current()->GetGpuChannel();
  return !!gpu_channel;
}

bool GpuBenchmarking::HasGpuProcess() {
  bool has_gpu_process = false;
  if (!RenderThreadImpl::current()->render_message_filter()->HasGpuProcess(
          &has_gpu_process)) {
    return false;
  }
  return has_gpu_process;
}

void GpuBenchmarking::CrashGpuProcess() {
  gpu::GpuChannelHost* gpu_channel =
      RenderThreadImpl::current()->GetGpuChannel();
  if (!gpu_channel)
    return;
  gpu_channel->CrashGpuProcessForTesting();
}

void GpuBenchmarking::GetGpuDriverBugWorkarounds(gin::Arguments* args) {
  std::vector<std::string> gpu_driver_bug_workarounds;
  gpu::GpuChannelHost* gpu_channel =
      RenderThreadImpl::current()->GetGpuChannel();
  if (!gpu_channel)
    return;
  const gpu::GpuFeatureInfo& gpu_feature_info = gpu_channel->gpu_feature_info();
  const std::vector<int32_t>& workarounds =
      gpu_feature_info.enabled_gpu_driver_bug_workarounds;
  for (int32_t workaround : workarounds) {
    gpu_driver_bug_workarounds.push_back(
        gpu::GpuDriverBugWorkaroundTypeToString(
            static_cast<gpu::GpuDriverBugWorkaroundType>(workaround)));
  }

  // This code must be kept in sync with compositor_util's
  // GetDriverBugWorkaroundsImpl.
  for (auto ext :
       base::SplitString(gpu_feature_info.disabled_extensions, " ",
                         base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
    gpu_driver_bug_workarounds.push_back("disabled_extension_" + ext);
  }
  for (auto ext :
       base::SplitString(gpu_feature_info.disabled_webgl_extensions, " ",
                         base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
    gpu_driver_bug_workarounds.push_back("disabled_webgl_extension_" + ext);
  }

  v8::Local<v8::Value> result;
  if (gin::TryConvertToV8(args->isolate(), gpu_driver_bug_workarounds, &result))
    args->Return(result);
}

void GpuBenchmarking::StartProfiling(gin::Arguments* args) {
  if (base::debug::BeingProfiled())
    return;
  std::string file_name;
  if (!GetOptionalArg(args, &file_name))
    return;
  if (!file_name.length())
    file_name = "profile.pb";
  base::debug::StartProfiling(file_name);
  base::debug::RestartProfilingAfterFork();
}

void GpuBenchmarking::StopProfiling() {
  if (base::debug::BeingProfiled())
    base::debug::StopProfiling();
}

void GpuBenchmarking::Freeze() {
  GpuBenchmarkingContext context;
  if (!context.Init(true))
    return;
  // TODO(fmeawad): Instead of forcing a visibility change, only allow
  // freezing a page if it was already hidden.
  context.web_view()->SetIsHidden(/*hidden=*/true,
                                  /*is_initial_state=*/false);
  context.web_view()->SetPageFrozen(true);
}

bool GpuBenchmarking::AddSwapCompletionEventListener(gin::Arguments* args) {
  v8::Local<v8::Function> callback;
  if (!GetArg(args, &callback))
    return false;
  if (!render_frame_)
    return false;
  LayerTreeView* layer_tree_view =
      render_frame_->GetLocalRootRenderWidget()->layer_tree_view();
  if (!layer_tree_view)
    return false;
  GpuBenchmarkingContext context;
  if (!context.Init(true))
    return false;

  auto callback_and_context = base::MakeRefCounted<CallbackAndContext>(
      args->isolate(), callback, context.web_frame()->MainWorldScriptContext());
  layer_tree_view->NotifySwapTime(base::BindOnce(
      &OnSwapCompletedHelper, base::RetainedRef(callback_and_context)));
  return true;
}

}  // namespace content
