Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1225)

Unified Diff: content/browser/devtools/protocol/devtools_protocol_browsertest.cc

Issue 2254923002: Adds a test for screenshot area capturing. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@eseckler_compositoroverrides
Patch Set: sync. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/browser/devtools/protocol/devtools_protocol_browsertest.cc
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
index e80582222fe74cca51e8deb44f12a85e7daddd5c..2a6d27ca3a82a21143552e519ab5b80f0f226c47 100644
--- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -6,15 +6,20 @@
#include <utility>
#include "base/base64.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
+#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "build/build_config.h"
#include "content/browser/frame_host/interstitial_page_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/interstitial_page_delegate.h"
@@ -39,8 +44,13 @@
#include "net/test/test_data_directory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/layout.h"
#include "ui/compositor/compositor_switches.h"
#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/skia_util.h"
#define EXPECT_SIZE_EQ(expected, actual) \
do { \
@@ -416,7 +426,143 @@ IN_PROC_BROWSER_TEST_F(SyntheticKeyEventTest, KeyEventSynthesizeKey) {
EXPECT_EQ("\"Escape\"", key);
}
+namespace {
+bool DecodePNG(std::string base64_data, SkBitmap* bitmap) {
+ std::string png_data;
+ if (!base::Base64Decode(base64_data, &png_data))
+ return false;
+ return gfx::PNGCodec::Decode(
+ reinterpret_cast<unsigned const char*>(png_data.data()), png_data.size(),
+ bitmap);
+}
+
+// Adapted from cc::ExactPixelComparator.
+bool MatchesBitmap(const SkBitmap& expected_bmp,
+ const SkBitmap& actual_bmp,
+ const gfx::Rect& matching_mask) {
+ // Number of pixels with an error
+ int error_pixels_count = 0;
+
+ gfx::Rect error_bounding_rect = gfx::Rect();
+
+ // Check that bitmaps have identical dimensions.
+ EXPECT_EQ(expected_bmp.width(), actual_bmp.width());
+ EXPECT_EQ(expected_bmp.height(), actual_bmp.height());
+ if (expected_bmp.width() != actual_bmp.width() ||
+ expected_bmp.height() != actual_bmp.height()) {
+ return false;
+ }
+
+ SkAutoLockPixels lock_actual_bmp(actual_bmp);
+ SkAutoLockPixels lock_expected_bmp(expected_bmp);
+
+ DCHECK(gfx::SkIRectToRect(actual_bmp.bounds()).Contains(matching_mask));
+
+ for (int x = matching_mask.x(); x < matching_mask.width(); ++x) {
+ for (int y = matching_mask.y(); y < matching_mask.height(); ++y) {
+ SkColor actual_color = actual_bmp.getColor(x, y);
+ SkColor expected_color = expected_bmp.getColor(x, y);
+ if (actual_color != expected_color) {
+ if (error_pixels_count < 10) {
+ LOG(ERROR) << "Pixel (" << x << "," << y << "): expected "
+ << expected_color << " actual " << actual_color;
+ }
+ error_pixels_count++;
+ error_bounding_rect.Union(gfx::Rect(x, y, 1, 1));
+ }
+ }
+ }
+
+ if (error_pixels_count != 0) {
+ LOG(ERROR) << "Number of pixel with an error: " << error_pixels_count;
+ LOG(ERROR) << "Error Bounding Box : " << error_bounding_rect.ToString();
+ return false;
+ }
+
+ return true;
+}
+} // namespace
+
class CaptureScreenshotTest : public DevToolsProtocolTest {
+ protected:
+ void CaptureScreenshotAndCompareTo(const SkBitmap& expected_bitmap) {
+ SendCommand("Page.captureScreenshot", nullptr);
+ std::string base64;
+ EXPECT_TRUE(result_->GetString("data", &base64));
+ SkBitmap result_bitmap;
+ EXPECT_TRUE(DecodePNG(base64, &result_bitmap));
+ gfx::Rect matching_mask(gfx::SkIRectToRect(expected_bitmap.bounds()));
+#if defined(OS_MACOSX)
+ // Mask out the corners, which may be drawn differently on Mac because of
+ // rounded corners.
+ matching_mask.Inset(4, 4, 4, 4);
+#endif
+ EXPECT_TRUE(MatchesBitmap(expected_bitmap, result_bitmap, matching_mask));
+ }
+
+ // Takes a screenshot of a colored box that is positioned inside the frame.
+ void PlaceAndCaptureBox(const gfx::Size& frame_size,
+ const gfx::Size& box_size,
+ float screenshot_scale) {
+ static const int kBoxOffsetHeight = 100;
+ const gfx::Size scaled_box_size =
+ ScaleToFlooredSize(box_size, screenshot_scale);
+ std::unique_ptr<base::DictionaryValue> params;
+
+ VLOG(1) << "Testing screenshot of box with size " << box_size.width() << "x"
+ << box_size.height() << "px at scale " << screenshot_scale
+ << " ...";
+
+ // Draw a blue box of provided size in the horizontal center of the page.
+ EXPECT_TRUE(content::ExecuteScript(
+ shell()->web_contents()->GetRenderViewHost(),
+ base::StringPrintf(
+ "var style = document.body.style; "
+ "style.overflow = 'hidden'; "
+ "style.minHeight = '%dpx'; "
+ "style.backgroundImage = 'linear-gradient(#0000ff, #0000ff)'; "
+ "style.backgroundSize = '%dpx %dpx'; "
+ "style.backgroundPosition = '50%% %dpx'; "
+ "style.backgroundRepeat = 'no-repeat'; ",
+ box_size.height() + kBoxOffsetHeight, box_size.width(),
+ box_size.height(), kBoxOffsetHeight)));
+
+ // Force frame size: The offset of the blue box within the frame shouldn't
+ // change during screenshotting. This verifies that the page doesn't observe
+ // a change in frame size as a side effect of screenshotting.
+ params.reset(new base::DictionaryValue());
+ params->SetInteger("width", frame_size.width());
+ params->SetInteger("height", frame_size.height());
+ params->SetDouble("deviceScaleFactor", 0);
+ params->SetBoolean("mobile", false);
+ params->SetBoolean("fitWindow", false);
+ SendCommand("Emulation.setDeviceMetricsOverride", std::move(params));
+
+ // Resize frame to scaled blue box size.
+ params.reset(new base::DictionaryValue());
+ params->SetInteger("width", scaled_box_size.width());
+ params->SetInteger("height", scaled_box_size.height());
+ SendCommand("Emulation.setVisibleSize", std::move(params));
+
+ // Force viewport to match scaled blue box.
+ params.reset(new base::DictionaryValue());
+ params->SetDouble("x", (frame_size.width() - box_size.width()) / 2.);
+ params->SetDouble("y", kBoxOffsetHeight);
+ params->SetDouble("scale", screenshot_scale);
+ SendCommand("Emulation.forceViewport", std::move(params));
+
+ // Capture screenshot and verify that it is indeed blue.
+ SkBitmap expected_bitmap;
+ expected_bitmap.allocN32Pixels(scaled_box_size.width(),
+ scaled_box_size.height());
+ expected_bitmap.eraseColor(SkColorSetRGB(0x00, 0x00, 0xff));
+ CaptureScreenshotAndCompareTo(expected_bitmap);
+
+ // Reset for next screenshot.
+ SendCommand("Emulation.resetViewport", nullptr);
+ SendCommand("Emulation.clearDeviceMetricsOverride", nullptr);
+ }
+
private:
#if !defined(OS_ANDROID)
void SetUpCommandLine(base::CommandLine* command_line) override {
@@ -425,32 +571,45 @@ class CaptureScreenshotTest : public DevToolsProtocolTest {
#endif
};
-// Does not link on Android
-#if !defined(OS_ANDROID)
IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, CaptureScreenshot) {
shell()->LoadURL(GURL("about:blank"));
Attach();
- EXPECT_TRUE(content::ExecuteScript(
- shell()->web_contents()->GetRenderViewHost(),
- "document.body.style.background = '#123456'"));
- SendCommand("Page.captureScreenshot", nullptr);
- std::string base64;
- EXPECT_TRUE(result_->GetString("data", &base64));
- std::string png;
- EXPECT_TRUE(base::Base64Decode(base64, &png));
- SkBitmap bitmap;
- gfx::PNGCodec::Decode(reinterpret_cast<const unsigned char*>(png.data()),
- png.size(), &bitmap);
- SkColor color(bitmap.getColor(0, 0));
- EXPECT_GE(1, std::abs(0x12-(int)SkColorGetR(color)));
- EXPECT_GE(1, std::abs(0x34-(int)SkColorGetG(color)));
- EXPECT_GE(1, std::abs(0x56-(int)SkColorGetB(color)));
- color = bitmap.getColor(1, 1);
- EXPECT_GE(1, std::abs(0x12-(int)SkColorGetR(color)));
- EXPECT_GE(1, std::abs(0x34-(int)SkColorGetG(color)));
- EXPECT_GE(1, std::abs(0x56-(int)SkColorGetB(color)));
+ EXPECT_TRUE(
+ content::ExecuteScript(shell()->web_contents()->GetRenderViewHost(),
+ "document.body.style.background = '#123456'"));
+ SkBitmap expected_bitmap;
+ // We compare against the actual physical backing size rather than the
+ // view size, because the view size is stored adjusted for DPI and only in
+ // integer precision.
+ gfx::Size view_size = static_cast<RenderWidgetHostViewBase*>(
+ shell()->web_contents()->GetRenderWidgetHostView())
+ ->GetPhysicalBackingSize();
+ expected_bitmap.allocN32Pixels(view_size.width(), view_size.height());
+ expected_bitmap.eraseColor(SkColorSetRGB(0x12, 0x34, 0x56));
+ CaptureScreenshotAndCompareTo(expected_bitmap);
}
+
+// Setting frame size (through RWHV) is not supported on Android.
+#if defined(OS_ANDROID)
+#define MAYBE_CaptureScreenshotArea DISABLED_CaptureScreenshotArea
+#else
+#define MAYBE_CaptureScreenshotArea CaptureScreenshotArea
#endif
+IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest,
+ MAYBE_CaptureScreenshotArea) {
+ static const gfx::Size kFrameSize(800, 600);
+
+ shell()->LoadURL(GURL("about:blank"));
+ Attach();
+
+ // Test capturing a subarea inside the emulated frame at different scales.
+ PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 1.0);
+ PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 2.0);
+ PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 0.5);
+
+ // Ensure that content outside the emulated frame is painted, too.
+ PlaceAndCaptureBox(kFrameSize, gfx::Size(10, 10000), 1.0);
+}
#if defined(OS_ANDROID)
// Disabled, see http://crbug.com/469947.
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698