OLD | NEW |
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...) Loading... |
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...) Loading... |
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...) Loading... |
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...) Loading... |
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 |
OLD | NEW |