Chromium Code Reviews

Side by Side Diff: content/browser/devtools/protocol/devtools_protocol_browsertest.cc

Issue 2592983002: [devtools] Support different encodings for Page.CaptureScreenshot. (Closed)
Patch Set: Disabled test on MacOS >=10.11, added ref to bug. Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <stddef.h> 5 #include <stddef.h>
6 #include <utility> 6 #include <utility>
7 7
8 #include "base/base64.h" 8 #include "base/base64.h"
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
(...skipping 31 matching lines...)
42 #include "content/test/content_browser_test_utils_internal.h" 42 #include "content/test/content_browser_test_utils_internal.h"
43 #include "net/dns/mock_host_resolver.h" 43 #include "net/dns/mock_host_resolver.h"
44 #include "net/test/cert_test_util.h" 44 #include "net/test/cert_test_util.h"
45 #include "net/test/embedded_test_server/embedded_test_server.h" 45 #include "net/test/embedded_test_server/embedded_test_server.h"
46 #include "net/test/test_data_directory.h" 46 #include "net/test/test_data_directory.h"
47 #include "testing/gmock/include/gmock/gmock.h" 47 #include "testing/gmock/include/gmock/gmock.h"
48 #include "third_party/skia/include/core/SkBitmap.h" 48 #include "third_party/skia/include/core/SkBitmap.h"
49 #include "third_party/skia/include/core/SkColor.h" 49 #include "third_party/skia/include/core/SkColor.h"
50 #include "ui/base/layout.h" 50 #include "ui/base/layout.h"
51 #include "ui/compositor/compositor_switches.h" 51 #include "ui/compositor/compositor_switches.h"
52 #include "ui/gfx/codec/jpeg_codec.h"
52 #include "ui/gfx/codec/png_codec.h" 53 #include "ui/gfx/codec/png_codec.h"
53 #include "ui/gfx/geometry/rect.h" 54 #include "ui/gfx/geometry/rect.h"
54 #include "ui/gfx/geometry/size.h" 55 #include "ui/gfx/geometry/size.h"
55 #include "ui/gfx/skia_util.h" 56 #include "ui/gfx/skia_util.h"
57 #include "ui/snapshot/snapshot.h"
56 58
57 #define EXPECT_SIZE_EQ(expected, actual) \ 59 #define EXPECT_SIZE_EQ(expected, actual) \
58 do { \ 60 do { \
59 EXPECT_EQ((expected).width(), (actual).width()); \ 61 EXPECT_EQ((expected).width(), (actual).width()); \
60 EXPECT_EQ((expected).height(), (actual).height()); \ 62 EXPECT_EQ((expected).height(), (actual).height()); \
61 } while (false) 63 } while (false)
62 64
63 using testing::ElementsAre; 65 using testing::ElementsAre;
64 66
65 namespace content { 67 namespace content {
(...skipping 458 matching lines...)
524 namespace { 526 namespace {
525 bool DecodePNG(std::string base64_data, SkBitmap* bitmap) { 527 bool DecodePNG(std::string base64_data, SkBitmap* bitmap) {
526 std::string png_data; 528 std::string png_data;
527 if (!base::Base64Decode(base64_data, &png_data)) 529 if (!base::Base64Decode(base64_data, &png_data))
528 return false; 530 return false;
529 return gfx::PNGCodec::Decode( 531 return gfx::PNGCodec::Decode(
530 reinterpret_cast<unsigned const char*>(png_data.data()), png_data.size(), 532 reinterpret_cast<unsigned const char*>(png_data.data()), png_data.size(),
531 bitmap); 533 bitmap);
532 } 534 }
533 535
536 std::unique_ptr<SkBitmap> DecodeJPEG(std::string base64_data) {
537 std::string jpeg_data;
538 if (!base::Base64Decode(base64_data, &jpeg_data))
539 return nullptr;
540 return gfx::JPEGCodec::Decode(
541 reinterpret_cast<unsigned const char*>(jpeg_data.data()),
542 jpeg_data.size());
543 }
544
545 bool ColorsMatchWithinLimit(SkColor color1,
546 SkColor color2,
547 int32_t error_limit) {
548 auto a_distance = std::abs(static_cast<int32_t>(SkColorGetA(color1)) -
549 static_cast<int32_t>(SkColorGetA(color2)));
550 auto r_distance = std::abs(static_cast<int32_t>(SkColorGetR(color1)) -
551 static_cast<int32_t>(SkColorGetR(color2)));
552 auto g_distance = std::abs(static_cast<int32_t>(SkColorGetG(color1)) -
553 static_cast<int32_t>(SkColorGetG(color2)));
554 auto b_distance = std::abs(static_cast<int32_t>(SkColorGetB(color1)) -
555 static_cast<int32_t>(SkColorGetB(color2)));
556
557 return a_distance * a_distance + r_distance * r_distance +
558 g_distance * g_distance + b_distance * b_distance <=
559 error_limit * error_limit;
560 }
561
534 // Adapted from cc::ExactPixelComparator. 562 // Adapted from cc::ExactPixelComparator.
535 bool MatchesBitmap(const SkBitmap& expected_bmp, 563 bool MatchesBitmap(const SkBitmap& expected_bmp,
536 const SkBitmap& actual_bmp, 564 const SkBitmap& actual_bmp,
537 const gfx::Rect& matching_mask) { 565 const gfx::Rect& matching_mask,
566 int error_limit) {
538 // Number of pixels with an error 567 // Number of pixels with an error
539 int error_pixels_count = 0; 568 int error_pixels_count = 0;
540 569
541 gfx::Rect error_bounding_rect = gfx::Rect(); 570 gfx::Rect error_bounding_rect = gfx::Rect();
542 571
543 // Check that bitmaps have identical dimensions. 572 // Check that bitmaps have identical dimensions.
544 EXPECT_EQ(expected_bmp.width(), actual_bmp.width()); 573 EXPECT_EQ(expected_bmp.width(), actual_bmp.width());
545 EXPECT_EQ(expected_bmp.height(), actual_bmp.height()); 574 EXPECT_EQ(expected_bmp.height(), actual_bmp.height());
546 if (expected_bmp.width() != actual_bmp.width() || 575 if (expected_bmp.width() != actual_bmp.width() ||
547 expected_bmp.height() != actual_bmp.height()) { 576 expected_bmp.height() != actual_bmp.height()) {
548 return false; 577 return false;
549 } 578 }
550 579
551 SkAutoLockPixels lock_actual_bmp(actual_bmp); 580 SkAutoLockPixels lock_actual_bmp(actual_bmp);
552 SkAutoLockPixels lock_expected_bmp(expected_bmp); 581 SkAutoLockPixels lock_expected_bmp(expected_bmp);
553 582
554 DCHECK(gfx::SkIRectToRect(actual_bmp.bounds()).Contains(matching_mask)); 583 DCHECK(gfx::SkIRectToRect(actual_bmp.bounds()).Contains(matching_mask));
555 584
556 for (int x = matching_mask.x(); x < matching_mask.width(); ++x) { 585 for (int x = matching_mask.x(); x < matching_mask.width(); ++x) {
557 for (int y = matching_mask.y(); y < matching_mask.height(); ++y) { 586 for (int y = matching_mask.y(); y < matching_mask.height(); ++y) {
558 SkColor actual_color = actual_bmp.getColor(x, y); 587 SkColor actual_color = actual_bmp.getColor(x, y);
559 SkColor expected_color = expected_bmp.getColor(x, y); 588 SkColor expected_color = expected_bmp.getColor(x, y);
560 if (actual_color != expected_color) { 589 if (!ColorsMatchWithinLimit(actual_color, expected_color, error_limit)) {
561 if (error_pixels_count < 10) { 590 if (error_pixels_count < 10) {
562 LOG(ERROR) << "Pixel (" << x << "," << y << "): expected " 591 LOG(ERROR) << "Pixel (" << x << "," << y << "): expected "
563 << expected_color << " actual " << actual_color; 592 << expected_color << " actual " << actual_color;
564 } 593 }
565 error_pixels_count++; 594 error_pixels_count++;
566 error_bounding_rect.Union(gfx::Rect(x, y, 1, 1)); 595 error_bounding_rect.Union(gfx::Rect(x, y, 1, 1));
567 } 596 }
568 } 597 }
569 } 598 }
570 599
571 if (error_pixels_count != 0) { 600 if (error_pixels_count != 0) {
572 LOG(ERROR) << "Number of pixel with an error: " << error_pixels_count; 601 LOG(ERROR) << "Number of pixel with an error: " << error_pixels_count;
573 LOG(ERROR) << "Error Bounding Box : " << error_bounding_rect.ToString(); 602 LOG(ERROR) << "Error Bounding Box : " << error_bounding_rect.ToString();
574 return false; 603 return false;
575 } 604 }
576 605
577 return true; 606 return true;
578 } 607 }
579 } // namespace 608 } // namespace
580 609
581 class CaptureScreenshotTest : public DevToolsProtocolTest { 610 class CaptureScreenshotTest : public DevToolsProtocolTest {
582 protected: 611 protected:
583 void CaptureScreenshotAndCompareTo(const SkBitmap& expected_bitmap) { 612 enum ScreenshotEncoding { ENCODING_PNG, ENCODING_JPEG };
584 SendCommand("Page.captureScreenshot", nullptr); 613 void CaptureScreenshotAndCompareTo(const SkBitmap& expected_bitmap,
614 ScreenshotEncoding encoding) {
615 std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
616 params->SetString("format", encoding == ENCODING_PNG ? "png" : "jpeg");
617 params->SetInteger("quality", 100);
618 SendCommand("Page.captureScreenshot", std::move(params));
619
585 std::string base64; 620 std::string base64;
586 EXPECT_TRUE(result_->GetString("data", &base64)); 621 EXPECT_TRUE(result_->GetString("data", &base64));
587 SkBitmap result_bitmap; 622 std::unique_ptr<SkBitmap> result_bitmap;
588 EXPECT_TRUE(DecodePNG(base64, &result_bitmap)); 623 int error_limit = 0;
624 if (encoding == ENCODING_PNG) {
625 result_bitmap.reset(new SkBitmap());
626 EXPECT_TRUE(DecodePNG(base64, result_bitmap.get()));
627 } else {
628 result_bitmap = DecodeJPEG(base64);
629 // Even with quality 100, jpeg isn't lossless. So, we allow some skew in
630 // pixel values. Not that this assumes that there is no skew in pixel
631 // positions, so will only work reliably if all pixels have equal values.
632 error_limit = 3;
633 }
634 EXPECT_TRUE(result_bitmap);
635
589 gfx::Rect matching_mask(gfx::SkIRectToRect(expected_bitmap.bounds())); 636 gfx::Rect matching_mask(gfx::SkIRectToRect(expected_bitmap.bounds()));
590 #if defined(OS_MACOSX) 637 #if defined(OS_MACOSX)
591 // Mask out the corners, which may be drawn differently on Mac because of 638 // Mask out the corners, which may be drawn differently on Mac because of
592 // rounded corners. 639 // rounded corners.
593 matching_mask.Inset(4, 4, 4, 4); 640 matching_mask.Inset(4, 4, 4, 4);
594 #endif 641 #endif
595 EXPECT_TRUE(MatchesBitmap(expected_bitmap, result_bitmap, matching_mask)); 642 EXPECT_TRUE(MatchesBitmap(expected_bitmap, *result_bitmap, matching_mask,
643 error_limit));
596 } 644 }
597 645
598 // Takes a screenshot of a colored box that is positioned inside the frame. 646 // Takes a screenshot of a colored box that is positioned inside the frame.
599 void PlaceAndCaptureBox(const gfx::Size& frame_size, 647 void PlaceAndCaptureBox(const gfx::Size& frame_size,
600 const gfx::Size& box_size, 648 const gfx::Size& box_size,
601 float screenshot_scale) { 649 float screenshot_scale) {
602 static const int kBoxOffsetHeight = 100; 650 static const int kBoxOffsetHeight = 100;
603 const gfx::Size scaled_box_size = 651 const gfx::Size scaled_box_size =
604 ScaleToFlooredSize(box_size, screenshot_scale); 652 ScaleToFlooredSize(box_size, screenshot_scale);
605 std::unique_ptr<base::DictionaryValue> params; 653 std::unique_ptr<base::DictionaryValue> params;
(...skipping 38 matching lines...)
644 params->SetDouble("x", (frame_size.width() - box_size.width()) / 2.); 692 params->SetDouble("x", (frame_size.width() - box_size.width()) / 2.);
645 params->SetDouble("y", kBoxOffsetHeight); 693 params->SetDouble("y", kBoxOffsetHeight);
646 params->SetDouble("scale", screenshot_scale); 694 params->SetDouble("scale", screenshot_scale);
647 SendCommand("Emulation.forceViewport", std::move(params)); 695 SendCommand("Emulation.forceViewport", std::move(params));
648 696
649 // Capture screenshot and verify that it is indeed blue. 697 // Capture screenshot and verify that it is indeed blue.
650 SkBitmap expected_bitmap; 698 SkBitmap expected_bitmap;
651 expected_bitmap.allocN32Pixels(scaled_box_size.width(), 699 expected_bitmap.allocN32Pixels(scaled_box_size.width(),
652 scaled_box_size.height()); 700 scaled_box_size.height());
653 expected_bitmap.eraseColor(SkColorSetRGB(0x00, 0x00, 0xff)); 701 expected_bitmap.eraseColor(SkColorSetRGB(0x00, 0x00, 0xff));
654 CaptureScreenshotAndCompareTo(expected_bitmap); 702 CaptureScreenshotAndCompareTo(expected_bitmap, ENCODING_PNG);
655 703
656 // Reset for next screenshot. 704 // Reset for next screenshot.
657 SendCommand("Emulation.resetViewport", nullptr); 705 SendCommand("Emulation.resetViewport", nullptr);
658 SendCommand("Emulation.clearDeviceMetricsOverride", nullptr); 706 SendCommand("Emulation.clearDeviceMetricsOverride", nullptr);
659 } 707 }
660 708
661 private: 709 private:
662 #if !defined(OS_ANDROID) 710 #if !defined(OS_ANDROID)
663 void SetUpCommandLine(base::CommandLine* command_line) override { 711 void SetUpCommandLine(base::CommandLine* command_line) override {
664 command_line->AppendSwitch(switches::kEnablePixelOutputInTests); 712 command_line->AppendSwitch(switches::kEnablePixelOutputInTests);
665 } 713 }
666 #endif 714 #endif
667 }; 715 };
668 716
669 IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, CaptureScreenshot) { 717 IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, CaptureScreenshot) {
670 // This test fails consistently on low-end Android devices. 718 // This test fails consistently on low-end Android devices.
671 // See crbug.com/653637. 719 // See crbug.com/653637.
720 // TODO(eseckler): Reenable with error limit if necessary.
672 if (base::SysInfo::IsLowEndDevice()) return; 721 if (base::SysInfo::IsLowEndDevice()) return;
673 722
674 shell()->LoadURL(GURL("about:blank")); 723 shell()->LoadURL(
724 GURL("data:text/html,<body style='background:#123456'></body>"));
725 WaitForLoadStop(shell()->web_contents());
675 Attach(); 726 Attach();
676 EXPECT_TRUE(
677 content::ExecuteScript(shell()->web_contents()->GetRenderViewHost(),
678 "document.body.style.background = '#123456'"));
679 SkBitmap expected_bitmap; 727 SkBitmap expected_bitmap;
680 // We compare against the actual physical backing size rather than the 728 // We compare against the actual physical backing size rather than the
681 // view size, because the view size is stored adjusted for DPI and only in 729 // view size, because the view size is stored adjusted for DPI and only in
730 // integer precision.
731 gfx::Size view_size = static_cast<RenderWidgetHostViewBase*>(
732 shell()->web_contents()->GetRenderWidgetHostView())
733 ->GetPhysicalBackingSize();
734 expected_bitmap.allocN32Pixels(view_size.width(), view_size.height());
735 expected_bitmap.eraseColor(SkColorSetRGB(0x12, 0x34, 0x56));
736 CaptureScreenshotAndCompareTo(expected_bitmap, ENCODING_PNG);
737 }
738
739 IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, CaptureScreenshotJpeg) {
740 // This test fails consistently on low-end Android devices.
741 // See crbug.com/653637.
742 // TODO(eseckler): Reenable with error limit if necessary.
743 if (base::SysInfo::IsLowEndDevice())
744 return;
745
746 shell()->LoadURL(
747 GURL("data:text/html,<body style='background:#123456'></body>"));
748 WaitForLoadStop(shell()->web_contents());
749 Attach();
750 SkBitmap expected_bitmap;
751 // We compare against the actual physical backing size rather than the
752 // view size, because the view size is stored adjusted for DPI and only in
682 // integer precision. 753 // integer precision.
683 gfx::Size view_size = static_cast<RenderWidgetHostViewBase*>( 754 gfx::Size view_size = static_cast<RenderWidgetHostViewBase*>(
684 shell()->web_contents()->GetRenderWidgetHostView()) 755 shell()->web_contents()->GetRenderWidgetHostView())
685 ->GetPhysicalBackingSize(); 756 ->GetPhysicalBackingSize();
686 expected_bitmap.allocN32Pixels(view_size.width(), view_size.height()); 757 expected_bitmap.allocN32Pixels(view_size.width(), view_size.height());
687 expected_bitmap.eraseColor(SkColorSetRGB(0x12, 0x34, 0x56)); 758 expected_bitmap.eraseColor(SkColorSetRGB(0x12, 0x34, 0x56));
688 CaptureScreenshotAndCompareTo(expected_bitmap); 759 CaptureScreenshotAndCompareTo(expected_bitmap, ENCODING_JPEG);
689 } 760 }
690 761
691 // Setting frame size (through RWHV) is not supported on Android. 762 // Setting frame size (through RWHV) is not supported on Android.
692 #if defined(OS_ANDROID) 763 #if defined(OS_ANDROID)
693 #define MAYBE_CaptureScreenshotArea DISABLED_CaptureScreenshotArea 764 #define MAYBE_CaptureScreenshotArea DISABLED_CaptureScreenshotArea
694 #else 765 #else
695 #define MAYBE_CaptureScreenshotArea CaptureScreenshotArea 766 #define MAYBE_CaptureScreenshotArea CaptureScreenshotArea
696 #endif 767 #endif
697 IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, 768 IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest,
698 MAYBE_CaptureScreenshotArea) { 769 MAYBE_CaptureScreenshotArea) {
(...skipping 875 matching lines...)
1574 EXPECT_EQ("polyglottal", value); 1645 EXPECT_EQ("polyglottal", value);
1575 found++; 1646 found++;
1576 } else { 1647 } else {
1577 FAIL(); 1648 FAIL();
1578 } 1649 }
1579 } 1650 }
1580 EXPECT_EQ(2u, found); 1651 EXPECT_EQ(2u, found);
1581 } 1652 }
1582 1653
1583 } // namespace content 1654 } // namespace content
OLDNEW

Powered by Google App Engine