Commit 3959a360 authored by Céline O'Neil's avatar Céline O'Neil Committed by Commit Bot

Fuzz a single SolidColorDrawQuad using protobuf-mutator.

Tests the SubmitCompositorFrame IPC interface of CompositorFrameSink by
submitting a CompositorFrame constructed from a fuzzed protobuf. This
frame is embedded in a CompositorFrame displayed by a mock browser.
The CompositorFrame contains exactly one DrawQuad of the type
SolidColorDrawQuad.

This CL sets up the framework needed for further, more thorough fuzzing
of the SubmitCompositorFrame interface, and isn't expected to have
thorough coverage just yet.

R=kylechar

Bug: 923088
Change-Id: Ie6ecc0526c6e524c8e1e54e76fa32ec7dd410211
Reviewed-on: https://chromium-review.googlesource.com/c/1456864
Commit-Queue: Céline O'Neil <celineo@google.com>
Reviewed-by: default avatarKen Rockot <rockot@google.com>
Reviewed-by: default avatarkylechar <kylechar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#634410}
parent e8eb4d78
...@@ -6,6 +6,7 @@ import("//build/config/ui.gni") ...@@ -6,6 +6,7 @@ import("//build/config/ui.gni")
import("//components/viz/viz.gni") import("//components/viz/viz.gni")
import("//gpu/vulkan/features.gni") import("//gpu/vulkan/features.gni")
import("//testing/libfuzzer/fuzzer_test.gni") import("//testing/libfuzzer/fuzzer_test.gni")
import("//third_party/protobuf/proto_library.gni")
config("viz_service_implementation") { config("viz_service_implementation") {
} }
...@@ -474,6 +475,32 @@ viz_source_set("perf_tests") { ...@@ -474,6 +475,32 @@ viz_source_set("perf_tests") {
] ]
} }
proto_library("compositor_frame_fuzzer_proto") {
sources = [
"compositor_frame_fuzzer/compositor_frame_fuzzer.proto",
]
}
fuzzer_test("compositor_frame_fuzzer") {
sources = [
"compositor_frame_fuzzer/compositor_frame_fuzzer.cc",
"compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc",
"compositor_frame_fuzzer/compositor_frame_fuzzer_util.h",
"compositor_frame_fuzzer/fuzzer_browser_process.cc",
"compositor_frame_fuzzer/fuzzer_browser_process.h",
"compositor_frame_fuzzer/fuzzer_software_display_provider.cc",
"compositor_frame_fuzzer/fuzzer_software_display_provider.h",
]
deps = [
":compositor_frame_fuzzer_proto",
":service",
"//components/viz/test:test_support",
"//mojo/core/embedder",
"//third_party/libprotobuf-mutator",
]
}
fuzzer_test("hit_test_manager_fuzzer") { fuzzer_test("hit_test_manager_fuzzer") {
sources = [ sources = [
"hit_test/hit_test_manager_fuzzer.cc", "hit_test/hit_test_manager_fuzzer.cc",
......
include_rules = [
"+components/viz/service",
"+components/viz/test",
]
specific_include_rules = {
"compositor_frame_fuzzer.cc": [
"+mojo/core/embedder",
]
}
// Copyright 2019 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 "base/command_line.h"
#include "base/message_loop/message_loop.h"
#include "base/no_destructor.h"
#include "components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.h"
#include "components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.h"
#include "mojo/core/embedder/embedder.h"
#include "testing/libfuzzer/proto/lpm_interface.h"
#include "components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer.pb.h"
namespace {
struct Env {
public:
Env() {
mojo::core::Init();
// Run fuzzer with the flag --dump-to-png[=dir-name] to dump the browser
// display into PNG files for debugging purposes.
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
auto png_dir_path =
command_line->HasSwitch("dump-to-png")
? base::Optional<base::FilePath>(
command_line->GetSwitchValuePath("dump-to-png"))
: base::nullopt;
browser_process = std::make_unique<viz::FuzzerBrowserProcess>(png_dir_path);
}
~Env() = default;
std::unique_ptr<viz::FuzzerBrowserProcess> browser_process;
private:
base::MessageLoop message_loop;
};
} // namespace
extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
base::CommandLine::Init(*argc, *argv);
return 0;
}
DEFINE_BINARY_PROTO_FUZZER(
const content::fuzzing::proto::RenderPass& render_pass_spec) {
static base::NoDestructor<Env> env;
viz::CompositorFrame frame =
viz::GenerateFuzzedCompositorFrame(render_pass_spec);
env->browser_process->EmbedFuzzedCompositorFrame(std::move(frame));
}
// Copyright 2019 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.
syntax = "proto2";
package content.fuzzing.proto;
message RenderPass {
required Rect output_rect = 1;
required Rect damage_rect = 2;
required SolidColorDrawQuad draw_quad = 3;
}
message SolidColorDrawQuad {
required Rect rect = 1;
required Rect visible_rect = 2;
required fixed32 color = 3 [default = 0xffffffff];
required bool force_anti_aliasing_off = 4;
}
// Spec to initialize a gfx::Rect.
// Defaults to the size of the renderer frame as defined in
// fuzzer_browser_process.cc, in the hopes that this generally yields more
// interesting values more quickly.
message Rect {
required sint32 x = 1 [default = 0];
required sint32 y = 2 [default = 0];
required sint32 width = 3 [default = 620];
required sint32 height = 4 [default = 400];
}
\ No newline at end of file
// Copyright 2019 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 "components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.h"
#include <memory>
#include <utility>
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.h"
namespace viz {
namespace {
gfx::Rect GetRectFromProtobuf(const content::fuzzing::proto::Rect& proto_rect) {
return gfx::Rect(proto_rect.x(), proto_rect.y(), proto_rect.width(),
proto_rect.height());
}
// Mutates a gfx::Rect to ensure width and height are both at least min_size.
// Use in case e.g. a 0-width/height Rect would cause a validation error on
// deserialization.
void ExpandToMinSize(gfx::Rect* rect, int min_size) {
if (rect->width() < min_size) {
// grow width to min_size in +x direction
// (may be clamped if x + min_size overflows)
rect->set_width(min_size);
}
// if previous attempt failed due to overflow
if (rect->width() < min_size) {
// grow width to min_size in -x direction
rect->Offset(-(min_size - rect->width()), 0);
rect->set_width(min_size);
}
if (rect->height() < min_size) {
// grow height to min_size in +y direction
// (may be clamped if y + min_size overflows)
rect->set_height(min_size);
}
// if previous attempt failed due to overflow
if (rect->height() < min_size) {
// grow height to min_size in -y direction
rect->Offset(0, -(min_size - rect->height()));
rect->set_height(min_size);
}
}
} // namespace
CompositorFrame GenerateFuzzedCompositorFrame(
const content::fuzzing::proto::RenderPass& render_pass_spec) {
CompositorFrame frame;
frame.metadata.begin_frame_ack.source_id = BeginFrameArgs::kManualSourceId;
frame.metadata.begin_frame_ack.sequence_number =
BeginFrameArgs::kStartingFrameNumber;
frame.metadata.begin_frame_ack.has_damage = true;
frame.metadata.frame_token = 1;
frame.metadata.device_scale_factor = 1;
frame.metadata.local_surface_id_allocation_time = base::TimeTicks::Now();
std::unique_ptr<RenderPass> pass = RenderPass::Create();
gfx::Rect rp_output_rect =
GetRectFromProtobuf(render_pass_spec.output_rect());
ExpandToMinSize(&rp_output_rect, 1);
pass->SetNew(1, rp_output_rect,
GetRectFromProtobuf(render_pass_spec.damage_rect()),
gfx::Transform());
content::fuzzing::proto::SolidColorDrawQuad quad_spec =
render_pass_spec.draw_quad();
gfx::Rect quad_rect = GetRectFromProtobuf(quad_spec.rect());
gfx::Rect quad_visible_rect = GetRectFromProtobuf(quad_spec.visible_rect());
auto* shared_quad_state = pass->CreateAndAppendSharedQuadState();
shared_quad_state->SetAll(gfx::Transform(), gfx::Rect(quad_rect),
gfx::Rect(quad_rect), gfx::Rect(quad_rect),
/*is_clipped=*/false,
/*are_contents_opaque=*/false, 1,
SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
color_quad->SetNew(shared_quad_state, quad_visible_rect, gfx::Rect(quad_rect),
quad_spec.color(), quad_spec.force_anti_aliasing_off());
frame.render_pass_list.push_back(std::move(pass));
return frame;
}
} // namespace viz
// Copyright 2019 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.
#ifndef COMPONENTS_VIZ_SERVICE_COMPOSITOR_FRAME_FUZZER_COMPOSITOR_FRAME_FUZZER_UTIL_H_
#define COMPONENTS_VIZ_SERVICE_COMPOSITOR_FRAME_FUZZER_COMPOSITOR_FRAME_FUZZER_UTIL_H_
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer.pb.h"
namespace viz {
// Converts a fuzzed specification in the form of a RenderPass protobuf message
// (as defined in compositor_frame_fuzzer.proto) into a CompositorFrame with a
// RenderPass member.
//
// Performs minimal validation and corrections to ensure that submitting the
// frame to a CompositorFrameSink will not result in a mojo deserialization
// validation error.
CompositorFrame GenerateFuzzedCompositorFrame(
const content::fuzzing::proto::RenderPass& render_pass_spec);
} // namespace viz
#endif // COMPONENTS_VIZ_SERVICE_COMPOSITOR_FRAME_FUZZER_COMPOSITOR_FRAME_FUZZER_UTIL_H_
// Copyright 2019 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 "components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.h"
#include <memory>
#include <utility>
#include "base/run_loop.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/quads/surface_draw_quad.h"
#include "components/viz/common/surfaces/surface_range.h"
namespace viz {
namespace {
// If modifying these sizes, consider also updating the default values in
// compositor_frame_fuzzer.proto to match.
constexpr gfx::Size kBrowserSize(620, 480);
constexpr gfx::Size kTopBarSize(620, 80);
constexpr gfx::Size kRendererFrameSize(620, 400);
constexpr FrameSinkId kEmbeddedFrameSinkId(2, 1);
constexpr FrameSinkId kRootFrameSinkId(1, 1);
} // namespace
FuzzerBrowserProcess::FuzzerBrowserProcess(
base::Optional<base::FilePath> png_dir_path)
: root_local_surface_id_(1, 1, base::UnguessableToken::Create()),
display_provider_(std::move(png_dir_path)),
frame_sink_manager_(&shared_bitmap_manager_,
base::nullopt,
&display_provider_) {
frame_sink_manager_.RegisterFrameSinkId(kEmbeddedFrameSinkId,
/*report_activation=*/false);
frame_sink_manager_.RegisterFrameSinkId(kRootFrameSinkId,
/*report_activation=*/false);
frame_sink_manager_.CreateRootCompositorFrameSink(
BuildRootCompositorFrameSinkParams());
display_private_->SetDisplayVisible(true);
display_private_->Resize(kBrowserSize);
}
FuzzerBrowserProcess::~FuzzerBrowserProcess() {
frame_sink_manager_.InvalidateFrameSinkId(kRootFrameSinkId);
frame_sink_manager_.InvalidateFrameSinkId(kEmbeddedFrameSinkId);
}
void FuzzerBrowserProcess::EmbedFuzzedCompositorFrame(
CompositorFrame fuzzed_frame) {
mojom::CompositorFrameSinkPtr sink_ptr;
FakeCompositorFrameSinkClient sink_client;
frame_sink_manager_.CreateCompositorFrameSink(kEmbeddedFrameSinkId,
mojo::MakeRequest(&sink_ptr),
sink_client.BindInterfacePtr());
lsi_allocator_.GenerateId();
SurfaceId embedded_surface_id(
kEmbeddedFrameSinkId,
lsi_allocator_.GetCurrentLocalSurfaceIdAllocation().local_surface_id());
sink_ptr->SubmitCompositorFrame(embedded_surface_id.local_surface_id(),
std::move(fuzzed_frame), base::nullopt, 0);
CompositorFrame browser_frame =
BuildBrowserUICompositorFrame(embedded_surface_id);
root_compositor_frame_sink_ptr_->SubmitCompositorFrame(
root_local_surface_id_, std::move(browser_frame), base::nullopt, 0);
display_private_->ForceImmediateDrawAndSwapIfPossible();
base::RunLoop().RunUntilIdle(); // needed to actually run queued messages
frame_sink_manager_.DestroyCompositorFrameSink(kEmbeddedFrameSinkId,
base::DoNothing());
}
mojom::RootCompositorFrameSinkParamsPtr
FuzzerBrowserProcess::BuildRootCompositorFrameSinkParams() {
auto params = mojom::RootCompositorFrameSinkParams::New();
params->frame_sink_id = kRootFrameSinkId;
params->widget = gpu::kNullSurfaceHandle;
params->gpu_compositing = false;
params->compositor_frame_sink = mojo::MakeRequestAssociatedWithDedicatedPipe(
&root_compositor_frame_sink_ptr_);
params->compositor_frame_sink_client =
root_compositor_frame_sink_client_.BindInterfacePtr().PassInterface();
params->display_private =
MakeRequestAssociatedWithDedicatedPipe(&display_private_);
params->display_client = display_client_.BindInterfacePtr().PassInterface();
return params;
}
CompositorFrame FuzzerBrowserProcess::BuildBrowserUICompositorFrame(
SurfaceId renderer_surface_id) {
CompositorFrame frame;
frame.metadata.begin_frame_ack.source_id = BeginFrameArgs::kManualSourceId;
frame.metadata.begin_frame_ack.sequence_number =
BeginFrameArgs::kStartingFrameNumber;
frame.metadata.device_scale_factor = 1;
frame.metadata.local_surface_id_allocation_time = base::TimeTicks::Now();
frame.metadata.referenced_surfaces.push_back(
SurfaceRange(base::nullopt, renderer_surface_id));
std::unique_ptr<RenderPass> pass = RenderPass::Create();
pass->SetNew(/*id=*/1, gfx::Rect(kBrowserSize), gfx::Rect(kBrowserSize),
gfx::Transform());
auto* renderer_sqs = pass->CreateAndAppendSharedQuadState();
renderer_sqs->SetAll(gfx::Transform(1.0, 0.0, 0.0, 1.0, 0, 80),
gfx::Rect(kRendererFrameSize),
gfx::Rect(kRendererFrameSize),
gfx::Rect(kRendererFrameSize), /*is_clipped=*/false,
/*are_contents_opaque=*/false, /*opacity=*/1,
SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
auto* surface_quad = pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
surface_quad->SetNew(renderer_sqs, gfx::Rect(kRendererFrameSize),
gfx::Rect(kRendererFrameSize),
SurfaceRange(base::nullopt, renderer_surface_id),
SK_ColorWHITE,
/*stretch_content_to_fill_bounds=*/false,
/*ignores_input_event=*/false);
auto* toolbar_sqs = pass->CreateAndAppendSharedQuadState();
toolbar_sqs->SetAll(gfx::Transform(), gfx::Rect(kTopBarSize),
gfx::Rect(kTopBarSize), gfx::Rect(kTopBarSize),
/*is_clipped=*/false, /*are_contents_opaque=*/false,
/*opacity=*/1, SkBlendMode::kSrcOver,
/*sorting_context_id=*/0);
auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
color_quad->SetNew(toolbar_sqs, gfx::Rect(kTopBarSize),
gfx::Rect(kTopBarSize), SK_ColorLTGRAY,
/*force_antialiasing_off=*/false);
frame.render_pass_list.push_back(std::move(pass));
return frame;
}
} // namespace viz
// Copyright 2019 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.
#ifndef COMPONENTS_VIZ_SERVICE_COMPOSITOR_FRAME_FUZZER_FUZZER_BROWSER_PROCESS_H_
#define COMPONENTS_VIZ_SERVICE_COMPOSITOR_FRAME_FUZZER_FUZZER_BROWSER_PROCESS_H_
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "components/viz/service/compositor_frame_fuzzer/fuzzer_software_display_provider.h"
#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "components/viz/test/fake_compositor_frame_sink_client.h"
#include "components/viz/test/fake_display_client.h"
namespace viz {
// A fake browser process to use as a fuzzer target.
// Uses software compositing.
class FuzzerBrowserProcess {
public:
explicit FuzzerBrowserProcess(base::Optional<base::FilePath> png_dir_path);
~FuzzerBrowserProcess();
// Fuzz target mimicking the process of submitting a rendered CompositorFrame
// to be embedded in the browser UI.
//
// Submits the provided fuzzed CompositorFrame to a new
// CompositorFrameSinkImpl.
//
// Submits a CompositorFrame to the RootCompositorFrameSinkImpl
// with a SolidColorDrawQuad "toolbar" and a SurfaceDrawQuad "renderer frame"
// embedding the fuzzed CompositorFrame.
void EmbedFuzzedCompositorFrame(CompositorFrame fuzzed_frame);
private:
mojom::RootCompositorFrameSinkParamsPtr BuildRootCompositorFrameSinkParams();
CompositorFrame BuildBrowserUICompositorFrame(SurfaceId renderer_surface_id);
const LocalSurfaceId root_local_surface_id_;
ServerSharedBitmapManager shared_bitmap_manager_;
FuzzerSoftwareDisplayProvider display_provider_;
FrameSinkManagerImpl frame_sink_manager_;
mojom::CompositorFrameSinkAssociatedPtr root_compositor_frame_sink_ptr_;
FakeCompositorFrameSinkClient root_compositor_frame_sink_client_;
mojom::DisplayPrivateAssociatedPtr display_private_;
FakeDisplayClient display_client_;
ParentLocalSurfaceIdAllocator lsi_allocator_;
DISALLOW_COPY_AND_ASSIGN(FuzzerBrowserProcess);
};
} // namespace viz
#endif // COMPONENTS_VIZ_SERVICE_COMPOSITOR_FRAME_FUZZER_FUZZER_BROWSER_PROCESS_H_
// Copyright 2019 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 "components/viz/service/compositor_frame_fuzzer/fuzzer_software_display_provider.h"
#include <string>
#include <utility>
#include <vector>
#include "base/files/file_util.h"
#include "components/viz/service/display/software_output_device.h"
#include "components/viz/service/display_embedder/software_output_surface.h"
#include "third_party/skia/include/encode/SkPngEncoder.h"
#include "ui/gfx/codec/png_codec.h"
namespace viz {
namespace {
// SoftwareOutputDevice that dumps the display's pixmap into a new PNG file per
// paint event. For debugging only: this significantly slows down fuzzing
// iterations and will not handle more than UINT32_MAX files.
class PNGSoftwareOutputDevice : public SoftwareOutputDevice {
public:
explicit PNGSoftwareOutputDevice(base::FilePath output_dir)
: output_dir_(output_dir) {}
// SoftwareOutputDevice implementation
void EndPaint() override {
SkPixmap input_pixmap;
surface_->peekPixels(&input_pixmap);
gfx::PNGCodec::ColorFormat color_format;
switch (input_pixmap.colorType()) {
case kRGBA_8888_SkColorType:
color_format = gfx::PNGCodec::FORMAT_RGBA;
break;
case kBGRA_8888_SkColorType:
color_format = gfx::PNGCodec::FORMAT_BGRA;
break;
default:
// failing to find a better default, this one is OK; PNGCodec::Encode
// will convert this to kN32_SkColorType
color_format = gfx::PNGCodec::FORMAT_SkBitmap;
break;
}
std::vector<unsigned char> output;
gfx::PNGCodec::Encode(
static_cast<const unsigned char*>(input_pixmap.addr()), color_format,
gfx::Size(input_pixmap.width(), input_pixmap.height()),
input_pixmap.rowBytes(),
/*discard_transparency=*/false,
/*comments=*/{}, &output);
base::WriteFile(NextOutputFilePath(),
reinterpret_cast<char*>(output.data()), output.size());
}
private:
// Return path of next output file. Will not handle overflow of file_id_.
base::FilePath NextOutputFilePath() {
// maximum possible length of next_file_id_ (in characters)
constexpr int kPaddedIntLength = 10;
std::string file_name =
base::StringPrintf("%0*u.png", kPaddedIntLength, next_file_id_++);
return output_dir_.Append(base::FilePath::FromUTF8Unsafe(file_name));
}
base::FilePath output_dir_;
uint32_t next_file_id_ = 0;
};
} // namespace
FuzzerSoftwareDisplayProvider::FuzzerSoftwareDisplayProvider(
base::Optional<base::FilePath> png_dir_path)
: png_dir_path_(png_dir_path),
begin_frame_source_(std::make_unique<StubBeginFrameSource>()) {}
FuzzerSoftwareDisplayProvider::~FuzzerSoftwareDisplayProvider() = default;
std::unique_ptr<Display> FuzzerSoftwareDisplayProvider::CreateDisplay(
const FrameSinkId& frame_sink_id,
gpu::SurfaceHandle surface_handle,
bool gpu_compositing,
mojom::DisplayClient* display_client,
ExternalBeginFrameSource* external_begin_frame_source,
SyntheticBeginFrameSource* synthetic_begin_frame_source,
const RendererSettings& renderer_settings,
bool send_swap_size_notifications) {
auto task_runner = base::ThreadTaskRunnerHandle::Get();
DCHECK(task_runner);
std::unique_ptr<SoftwareOutputDevice> software_output_device =
png_dir_path_ ? std::make_unique<PNGSoftwareOutputDevice>(*png_dir_path_)
: std::make_unique<SoftwareOutputDevice>();
auto output_surface = std::make_unique<SoftwareOutputSurface>(
std::move(software_output_device), synthetic_begin_frame_source);
auto scheduler = std::make_unique<DisplayScheduler>(
begin_frame_source_.get(), task_runner.get(),
output_surface->capabilities().max_frames_pending);
return std::make_unique<Display>(&shared_bitmap_manager_, renderer_settings,
frame_sink_id, std::move(output_surface),
std::move(scheduler), task_runner);
}
uint32_t FuzzerSoftwareDisplayProvider::GetRestartId() const {
return BeginFrameSource::kNotRestartableId;
}
} // namespace viz
// Copyright 2019 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.
#ifndef COMPONENTS_VIZ_SERVICE_COMPOSITOR_FRAME_FUZZER_FUZZER_SOFTWARE_DISPLAY_PROVIDER_H_
#define COMPONENTS_VIZ_SERVICE_COMPOSITOR_FRAME_FUZZER_FUZZER_SOFTWARE_DISPLAY_PROVIDER_H_
#include <memory>
#include "components/viz/service/display/display.h"
#include "components/viz/service/display_embedder/display_provider.h"
#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
namespace viz {
// DisplayProvider implementation that provides Displays that use a
// SoftwareOutputSurface (no-op by default, with an option to dump pixmap to a
// PNG for debugging).
//
// Provided Displays will only draw when explicitly asked to
// (e.g. if Display::ForceImmediateDrawAndSwapIfPossible() is called),
// ignoring the BeginFrameSource parameters passed to CreateDisplay.
class FuzzerSoftwareDisplayProvider : public DisplayProvider {
public:
explicit FuzzerSoftwareDisplayProvider(
base::Optional<base::FilePath> png_dir_path);
~FuzzerSoftwareDisplayProvider() override;
// DisplayProvider implementation.
std::unique_ptr<Display> CreateDisplay(
const FrameSinkId& frame_sink_id,
gpu::SurfaceHandle surface_handle,
bool gpu_compositing,
mojom::DisplayClient* display_client,
ExternalBeginFrameSource* external_begin_frame_source,
SyntheticBeginFrameSource* synthetic_begin_frame_source,
const RendererSettings& renderer_settings,
bool send_swap_size_notifications) override;
uint32_t GetRestartId() const override;
private:
base::Optional<base::FilePath> png_dir_path_;
ServerSharedBitmapManager shared_bitmap_manager_;
std::unique_ptr<StubBeginFrameSource> begin_frame_source_;
DISALLOW_COPY_AND_ASSIGN(FuzzerSoftwareDisplayProvider);
};
} // namespace viz
#endif // COMPONENTS_VIZ_SERVICE_COMPOSITOR_FRAME_FUZZER_FUZZER_SOFTWARE_DISPLAY_PROVIDER_H_
...@@ -17,6 +17,8 @@ viz_static_library("test_support") { ...@@ -17,6 +17,8 @@ viz_static_library("test_support") {
"fake_compositor_frame_sink_client.h", "fake_compositor_frame_sink_client.h",
"fake_delay_based_time_source.cc", "fake_delay_based_time_source.cc",
"fake_delay_based_time_source.h", "fake_delay_based_time_source.h",
"fake_display_client.cc",
"fake_display_client.h",
"fake_external_begin_frame_source.cc", "fake_external_begin_frame_source.cc",
"fake_external_begin_frame_source.h", "fake_external_begin_frame_source.h",
"fake_host_frame_sink_client.cc", "fake_host_frame_sink_client.cc",
......
...@@ -6,7 +6,8 @@ ...@@ -6,7 +6,8 @@
namespace viz { namespace viz {
FakeCompositorFrameSinkClient::FakeCompositorFrameSinkClient() = default; FakeCompositorFrameSinkClient::FakeCompositorFrameSinkClient()
: binding_(this) {}
FakeCompositorFrameSinkClient::~FakeCompositorFrameSinkClient() = default; FakeCompositorFrameSinkClient::~FakeCompositorFrameSinkClient() = default;
void FakeCompositorFrameSinkClient::DidReceiveCompositorFrameAck( void FakeCompositorFrameSinkClient::DidReceiveCompositorFrameAck(
...@@ -31,4 +32,11 @@ void FakeCompositorFrameSinkClient::InsertResources( ...@@ -31,4 +32,11 @@ void FakeCompositorFrameSinkClient::InsertResources(
resources.end()); resources.end());
} }
mojom::CompositorFrameSinkClientPtr
FakeCompositorFrameSinkClient::BindInterfacePtr() {
mojom::CompositorFrameSinkClientPtr ptr;
binding_.Bind(MakeRequest(&ptr));
return ptr;
}
} // namespace viz } // namespace viz
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <vector> #include <vector>
#include "components/viz/common/surfaces/local_surface_id.h" #include "components/viz/common/surfaces/local_surface_id.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h" #include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
namespace viz { namespace viz {
...@@ -17,6 +18,8 @@ class FakeCompositorFrameSinkClient : public mojom::CompositorFrameSinkClient { ...@@ -17,6 +18,8 @@ class FakeCompositorFrameSinkClient : public mojom::CompositorFrameSinkClient {
FakeCompositorFrameSinkClient(); FakeCompositorFrameSinkClient();
~FakeCompositorFrameSinkClient() override; ~FakeCompositorFrameSinkClient() override;
mojom::CompositorFrameSinkClientPtr BindInterfacePtr();
// mojom::CompositorFrameSinkClient implementation. // mojom::CompositorFrameSinkClient implementation.
void DidReceiveCompositorFrameAck( void DidReceiveCompositorFrameAck(
const std::vector<ReturnedResource>& resources) override; const std::vector<ReturnedResource>& resources) override;
...@@ -37,6 +40,8 @@ class FakeCompositorFrameSinkClient : public mojom::CompositorFrameSinkClient { ...@@ -37,6 +40,8 @@ class FakeCompositorFrameSinkClient : public mojom::CompositorFrameSinkClient {
std::vector<ReturnedResource> returned_resources_; std::vector<ReturnedResource> returned_resources_;
mojo::Binding<mojom::CompositorFrameSinkClient> binding_;
DISALLOW_COPY_AND_ASSIGN(FakeCompositorFrameSinkClient); DISALLOW_COPY_AND_ASSIGN(FakeCompositorFrameSinkClient);
}; };
......
// Copyright 2019 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 "components/viz/test/fake_display_client.h"
namespace viz {
FakeDisplayClient::FakeDisplayClient() : binding_(this) {}
FakeDisplayClient::~FakeDisplayClient() = default;
void FakeDisplayClient::DidSwapAfterSnapshotRequestReceived(
const std::vector<ui::LatencyInfo>&) {}
mojom::DisplayClientPtr FakeDisplayClient::BindInterfacePtr() {
mojom::DisplayClientPtr ptr;
binding_.Bind(MakeRequest(&ptr));
return ptr;
}
#if defined(OS_MACOSX)
void FakeDisplayClient::OnDisplayReceivedCALayerParams(
const gfx::CALayerParams& ca_layer_params) {}
#endif
#if defined(OS_WIN)
void FakeDisplayClient::CreateLayeredWindowUpdater(
mojom::LayeredWindowUpdaterRequest request) {}
#endif
} // namespace viz
// Copyright 2019 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.
#ifndef COMPONENTS_VIZ_TEST_FAKE_DISPLAY_CLIENT_H_
#define COMPONENTS_VIZ_TEST_FAKE_DISPLAY_CLIENT_H_
#include <vector>
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/viz/privileged/interfaces/compositing/display_private.mojom.h"
namespace viz {
class FakeDisplayClient : public mojom::DisplayClient {
public:
FakeDisplayClient();
~FakeDisplayClient() override;
mojom::DisplayClientPtr BindInterfacePtr();
// mojom::DisplayClient implementation.
void DidSwapAfterSnapshotRequestReceived(
const std::vector<ui::LatencyInfo>&) override;
#if defined(OS_MACOSX)
void OnDisplayReceivedCALayerParams(
const gfx::CALayerParams& ca_layer_params) override;
#endif
#if defined(OS_WIN)
void CreateLayeredWindowUpdater(
mojom::LayeredWindowUpdaterRequest request) override;
#endif
private:
mojo::Binding<mojom::DisplayClient> binding_;
DISALLOW_COPY_AND_ASSIGN(FakeDisplayClient);
};
} // namespace viz
#endif // COMPONENTS_VIZ_TEST_FAKE_DISPLAY_CLIENT_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment