#include "content/renderer/gpu_benchmarking_extension.h"
#include <stddef.h>
#include <memory>
#include <string>
#include <string_view>
#include <tuple>
#include <utility>
#include <vector>
#include "base/base64.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/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.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/input_injector.mojom.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/render_frame_impl.h"
#include "content/renderer/render_thread_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 "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/common/input/web_mouse_event.h"
#include "third_party/blink/public/mojom/page/page_visibility_state.mojom.h"
#include "third_party/blink/public/platform/browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h"
#include "third_party/blink/public/web/modules/canvas/canvas_test_utils.h"
#include "third_party/blink/public/web/web_frame_widget.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/SkDocument.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkSerialProcs.h"
#include "third_party/skia/include/core/SkStream.h"
#include "third_party/skia/include/docs/SkMultiPictureDocument.h"
#include "third_party/skia/include/docs/SkXPSDocument.h"
#include "third_party/skia/include/encode/SkPngEncoder.h"
#include "ui/events/base_event_utils.h"
#include "ui/gfx/ca_layer_result.h"
#include "ui/gfx/geometry/size_f.h"
#include "v8/include/v8-context.h"
#include "v8/include/v8-exception.h"
#include "v8/include/v8-function.h"
#include "v8/include/v8-isolate.h"
#include "v8/include/v8-object.h"
#include "v8/include/v8-persistent-handle.h"
#include "v8/include/v8-primitive.h"
#if BUILDFLAG(IS_WIN) && !defined(NDEBUG)
#include "base/win/wincrypt_shim.h"
#include <objbase.h>
#include <XpsObjectModel.h>
#include <wrl/client.h>
#endif
namespace blink {
class GpuBenchmarkingContext { … };
}
GpuBenchmarkingContext;
WebImageCache;
WebLocalFrame;
WebView;
namespace content {
namespace {
int GestureSourceTypeAsInt(content::mojom::GestureSourceType type) { … }
class SkPictureSerializer { … };
template <typename T>
bool GetArg(gin::Arguments* args, T* value) { … }
template <>
bool GetArg(gin::Arguments* args, int* value) { … }
template <typename T>
bool GetOptionalArg(gin::Arguments* args, T* value) { … }
class CallbackAndContext : public base::RefCounted<CallbackAndContext> { … };
void RunCallbackHelper(CallbackAndContext* callback_and_context,
std::optional<base::Value> value) { … }
void OnMicroBenchmarkCompleted(CallbackAndContext* callback_and_context,
base::Value::Dict result) { … }
#if BUILDFLAG(IS_MAC)
void OnSwapCompletedWithCoreAnimationErrorCode(
CallbackAndContext* callback_and_context,
gfx::CALayerResult error_code) {
RunCallbackHelper(callback_and_context,
std::optional<base::Value>(base::Value(error_code)));
}
#endif
void OnSyntheticGestureCompleted(CallbackAndContext* callback_and_context) { … }
bool ThrowIfPointOutOfBounds(GpuBenchmarkingContext* context,
gin::Arguments* args,
const gfx::Point& point,
const std::string& message) { … }
std::optional<gfx::Vector2dF> ToVector(const std::string& direction,
float distance) { … }
int ToKeyModifiers(std::string_view key) { … }
int ToButtonModifiers(std::string_view button) { … }
bool BeginSmoothScroll(GpuBenchmarkingContext* context,
gin::Arguments* args,
const mojo::Remote<mojom::InputInjector>& injector,
const gfx::Vector2dF& pixels_to_scroll,
v8::Local<v8::Function> callback,
int gesture_source_type,
float speed_in_pixels_s,
bool prevent_fling,
float start_x,
float start_y,
const gfx::Vector2dF& fling_velocity,
bool precise_scrolling_deltas,
bool scroll_by_page,
bool cursor_visible,
bool scroll_by_percentage,
int modifiers,
float vsync_offset_ms,
int input_event_pattern) { … }
bool BeginSmoothDrag(GpuBenchmarkingContext* context,
gin::Arguments* args,
const mojo::Remote<mojom::InputInjector>& 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,
float vsync_offset_ms,
int input_event_pattern) { … }
static void PrintDocument(blink::WebLocalFrame* frame, SkDocument* doc) { … }
static void PrintDocumentTofile(v8::Isolate* isolate,
const std::string& filename,
sk_sp<SkDocument> (*make_doc)(SkWStream*),
RenderFrameImpl* render_frame) { … }
void OnSwapCompletedHelper(CallbackAndContext* callback_and_context,
const viz::FrameTimingDetails&) { … }
#if BUILDFLAG(IS_WIN) && !defined(NDEBUG)
static sk_sp<SkDocument> MakeXPSDocument(SkWStream* s) {
std::ignore = CoInitializeEx(
nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
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
}
gin::WrapperInfo GpuBenchmarking::kWrapperInfo = …;
void GpuBenchmarking::Install(base::WeakPtr<RenderFrameImpl> frame) { … }
GpuBenchmarking::GpuBenchmarking(base::WeakPtr<RenderFrameImpl> frame)
: … { … }
GpuBenchmarking::~GpuBenchmarking() = default;
void GpuBenchmarking::EnsureRemoteInterface() { … }
gin::ObjectTemplateBuilder GpuBenchmarking::GetObjectTemplateBuilder(
v8::Isolate* isolate) { … }
void GpuBenchmarking::SetNeedsDisplayOnAllLayers() { … }
void GpuBenchmarking::SetRasterizeOnlyVisibleContent() { … }
namespace {
sk_sp<SkDocument> make_multipicturedocument(SkWStream* stream) { … }
}
void GpuBenchmarking::PrintPagesToSkPictures(v8::Isolate* isolate,
const std::string& filename) { … }
void GpuBenchmarking::PrintPagesToXPS(v8::Isolate* isolate,
const std::string& filename) { … }
void GpuBenchmarking::PrintToSkPicture(v8::Isolate* isolate,
const std::string& dirname) { … }
bool GpuBenchmarking::GestureSourceTypeSupported(int gesture_source_type) { … }
bool GpuBenchmarking::SmoothScrollBy(gin::Arguments* args) { … }
bool GpuBenchmarking::SmoothScrollByXY(gin::Arguments* args) { … }
bool GpuBenchmarking::SmoothDrag(gin::Arguments* args) { … }
bool GpuBenchmarking::Swipe(gin::Arguments* args) { … }
bool GpuBenchmarking::ScrollBounce(gin::Arguments* args) { … }
bool GpuBenchmarking::PinchBy(gin::Arguments* args) { … }
float GpuBenchmarking::PageScaleFactor() { … }
void GpuBenchmarking::SetPageScaleFactor(float scale) { … }
void GpuBenchmarking::SetBrowserControlsShown(bool show) { … }
float GpuBenchmarking::VisualViewportY() { … }
float GpuBenchmarking::VisualViewportX() { … }
float GpuBenchmarking::VisualViewportHeight() { … }
float GpuBenchmarking::VisualViewportWidth() { … }
bool GpuBenchmarking::Tap(gin::Arguments* args) { … }
bool GpuBenchmarking::PointerActionSequence(gin::Arguments* args) { … }
void GpuBenchmarking::ClearImageCache() { … }
int GpuBenchmarking::RunMicroBenchmark(gin::Arguments* args) { … }
bool GpuBenchmarking::SendMessageToMicroBenchmark(
int id,
v8::Local<v8::Object> message) { … }
bool GpuBenchmarking::HasGpuChannel() { … }
bool GpuBenchmarking::HasGpuProcess() { … }
void GpuBenchmarking::CrashGpuProcess() { … }
void GpuBenchmarking::TerminateGpuProcessNormally() { … }
void GpuBenchmarking::GetGpuDriverBugWorkarounds(gin::Arguments* args) { … }
void GpuBenchmarking::StartProfiling(gin::Arguments* args) { … }
void GpuBenchmarking::StopProfiling() { … }
void GpuBenchmarking::Freeze() { … }
bool GpuBenchmarking::AddSwapCompletionEventListener(gin::Arguments* args) { … }
#if BUILDFLAG(IS_MAC)
int GpuBenchmarking::AddCoreAnimationStatusEventListener(gin::Arguments* args) {
v8::Local<v8::Function> callback;
if (!GetArg(args, &callback))
return false;
GpuBenchmarkingContext context(render_frame_.get());
auto callback_and_context = base::MakeRefCounted<CallbackAndContext>(
args->isolate(), callback, context.web_frame()->MainWorldScriptContext());
context.frame_widget()->NotifyCoreAnimationErrorCode(
base::BindOnce(&OnSwapCompletedWithCoreAnimationErrorCode,
base::RetainedRef(callback_and_context)));
context.layer_tree_host()->SetNeedsAnimateIfNotInsideMainFrame();
return true;
}
#endif
bool GpuBenchmarking::IsAcceleratedCanvasImageSource(gin::Arguments* args) { … }
}