| 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...) Expand 10 before | Expand all | Expand 10 after  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" |  | 
| 53 #include "ui/gfx/codec/png_codec.h" | 52 #include "ui/gfx/codec/png_codec.h" | 
| 54 #include "ui/gfx/geometry/rect.h" | 53 #include "ui/gfx/geometry/rect.h" | 
| 55 #include "ui/gfx/geometry/size.h" | 54 #include "ui/gfx/geometry/size.h" | 
| 56 #include "ui/gfx/skia_util.h" | 55 #include "ui/gfx/skia_util.h" | 
| 57 #include "ui/snapshot/snapshot.h" |  | 
| 58 | 56 | 
| 59 #define EXPECT_SIZE_EQ(expected, actual)               \ | 57 #define EXPECT_SIZE_EQ(expected, actual)               \ | 
| 60   do {                                                 \ | 58   do {                                                 \ | 
| 61     EXPECT_EQ((expected).width(), (actual).width());   \ | 59     EXPECT_EQ((expected).width(), (actual).width());   \ | 
| 62     EXPECT_EQ((expected).height(), (actual).height()); \ | 60     EXPECT_EQ((expected).height(), (actual).height()); \ | 
| 63   } while (false) | 61   } while (false) | 
| 64 | 62 | 
| 65 using testing::ElementsAre; | 63 using testing::ElementsAre; | 
| 66 | 64 | 
| 67 namespace content { | 65 namespace content { | 
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 459 namespace { | 457 namespace { | 
| 460 bool DecodePNG(std::string base64_data, SkBitmap* bitmap) { | 458 bool DecodePNG(std::string base64_data, SkBitmap* bitmap) { | 
| 461   std::string png_data; | 459   std::string png_data; | 
| 462   if (!base::Base64Decode(base64_data, &png_data)) | 460   if (!base::Base64Decode(base64_data, &png_data)) | 
| 463     return false; | 461     return false; | 
| 464   return gfx::PNGCodec::Decode( | 462   return gfx::PNGCodec::Decode( | 
| 465       reinterpret_cast<unsigned const char*>(png_data.data()), png_data.size(), | 463       reinterpret_cast<unsigned const char*>(png_data.data()), png_data.size(), | 
| 466       bitmap); | 464       bitmap); | 
| 467 } | 465 } | 
| 468 | 466 | 
| 469 std::unique_ptr<SkBitmap> DecodeJPEG(std::string base64_data) { |  | 
| 470   std::string jpeg_data; |  | 
| 471   if (!base::Base64Decode(base64_data, &jpeg_data)) |  | 
| 472     return nullptr; |  | 
| 473   return gfx::JPEGCodec::Decode( |  | 
| 474       reinterpret_cast<unsigned const char*>(jpeg_data.data()), |  | 
| 475       jpeg_data.size()); |  | 
| 476 } |  | 
| 477 |  | 
| 478 bool ColorsMatchWithinLimit(SkColor color1, |  | 
| 479                             SkColor color2, |  | 
| 480                             int32_t error_limit) { |  | 
| 481   auto a_distance = std::abs(static_cast<int32_t>(SkColorGetA(color1)) - |  | 
| 482                              static_cast<int32_t>(SkColorGetA(color2))); |  | 
| 483   auto r_distance = std::abs(static_cast<int32_t>(SkColorGetR(color1)) - |  | 
| 484                              static_cast<int32_t>(SkColorGetR(color2))); |  | 
| 485   auto g_distance = std::abs(static_cast<int32_t>(SkColorGetG(color1)) - |  | 
| 486                              static_cast<int32_t>(SkColorGetG(color2))); |  | 
| 487   auto b_distance = std::abs(static_cast<int32_t>(SkColorGetB(color1)) - |  | 
| 488                              static_cast<int32_t>(SkColorGetB(color2))); |  | 
| 489 |  | 
| 490   return a_distance * a_distance + r_distance * r_distance + |  | 
| 491              g_distance * g_distance + b_distance * b_distance <= |  | 
| 492          error_limit * error_limit; |  | 
| 493 } |  | 
| 494 |  | 
| 495 // Adapted from cc::ExactPixelComparator. | 467 // Adapted from cc::ExactPixelComparator. | 
| 496 bool MatchesBitmap(const SkBitmap& expected_bmp, | 468 bool MatchesBitmap(const SkBitmap& expected_bmp, | 
| 497                    const SkBitmap& actual_bmp, | 469                    const SkBitmap& actual_bmp, | 
| 498                    const gfx::Rect& matching_mask, | 470                    const gfx::Rect& matching_mask) { | 
| 499                    int error_limit) { |  | 
| 500   // Number of pixels with an error | 471   // Number of pixels with an error | 
| 501   int error_pixels_count = 0; | 472   int error_pixels_count = 0; | 
| 502 | 473 | 
| 503   gfx::Rect error_bounding_rect = gfx::Rect(); | 474   gfx::Rect error_bounding_rect = gfx::Rect(); | 
| 504 | 475 | 
| 505   // Check that bitmaps have identical dimensions. | 476   // Check that bitmaps have identical dimensions. | 
| 506   EXPECT_EQ(expected_bmp.width(), actual_bmp.width()); | 477   EXPECT_EQ(expected_bmp.width(), actual_bmp.width()); | 
| 507   EXPECT_EQ(expected_bmp.height(), actual_bmp.height()); | 478   EXPECT_EQ(expected_bmp.height(), actual_bmp.height()); | 
| 508   if (expected_bmp.width() != actual_bmp.width() || | 479   if (expected_bmp.width() != actual_bmp.width() || | 
| 509       expected_bmp.height() != actual_bmp.height()) { | 480       expected_bmp.height() != actual_bmp.height()) { | 
| 510     return false; | 481     return false; | 
| 511   } | 482   } | 
| 512 | 483 | 
| 513   SkAutoLockPixels lock_actual_bmp(actual_bmp); | 484   SkAutoLockPixels lock_actual_bmp(actual_bmp); | 
| 514   SkAutoLockPixels lock_expected_bmp(expected_bmp); | 485   SkAutoLockPixels lock_expected_bmp(expected_bmp); | 
| 515 | 486 | 
| 516   DCHECK(gfx::SkIRectToRect(actual_bmp.bounds()).Contains(matching_mask)); | 487   DCHECK(gfx::SkIRectToRect(actual_bmp.bounds()).Contains(matching_mask)); | 
| 517 | 488 | 
| 518   for (int x = matching_mask.x(); x < matching_mask.width(); ++x) { | 489   for (int x = matching_mask.x(); x < matching_mask.width(); ++x) { | 
| 519     for (int y = matching_mask.y(); y < matching_mask.height(); ++y) { | 490     for (int y = matching_mask.y(); y < matching_mask.height(); ++y) { | 
| 520       SkColor actual_color = actual_bmp.getColor(x, y); | 491       SkColor actual_color = actual_bmp.getColor(x, y); | 
| 521       SkColor expected_color = expected_bmp.getColor(x, y); | 492       SkColor expected_color = expected_bmp.getColor(x, y); | 
| 522       if (!ColorsMatchWithinLimit(actual_color, expected_color, error_limit)) { | 493       if (actual_color != expected_color) { | 
| 523         if (error_pixels_count < 10) { | 494         if (error_pixels_count < 10) { | 
| 524           LOG(ERROR) << "Pixel (" << x << "," << y << "): expected " | 495           LOG(ERROR) << "Pixel (" << x << "," << y << "): expected " | 
| 525                      << expected_color << " actual " << actual_color; | 496                      << expected_color << " actual " << actual_color; | 
| 526         } | 497         } | 
| 527         error_pixels_count++; | 498         error_pixels_count++; | 
| 528         error_bounding_rect.Union(gfx::Rect(x, y, 1, 1)); | 499         error_bounding_rect.Union(gfx::Rect(x, y, 1, 1)); | 
| 529       } | 500       } | 
| 530     } | 501     } | 
| 531   } | 502   } | 
| 532 | 503 | 
| 533   if (error_pixels_count != 0) { | 504   if (error_pixels_count != 0) { | 
| 534     LOG(ERROR) << "Number of pixel with an error: " << error_pixels_count; | 505     LOG(ERROR) << "Number of pixel with an error: " << error_pixels_count; | 
| 535     LOG(ERROR) << "Error Bounding Box : " << error_bounding_rect.ToString(); | 506     LOG(ERROR) << "Error Bounding Box : " << error_bounding_rect.ToString(); | 
| 536     return false; | 507     return false; | 
| 537   } | 508   } | 
| 538 | 509 | 
| 539   return true; | 510   return true; | 
| 540 } | 511 } | 
| 541 }  // namespace | 512 }  // namespace | 
| 542 | 513 | 
| 543 class CaptureScreenshotTest : public DevToolsProtocolTest { | 514 class CaptureScreenshotTest : public DevToolsProtocolTest { | 
| 544  protected: | 515  protected: | 
| 545   enum ScreenshotEncoding { ENCODING_PNG, ENCODING_JPEG }; | 516   void CaptureScreenshotAndCompareTo(const SkBitmap& expected_bitmap) { | 
| 546   void CaptureScreenshotAndCompareTo(const SkBitmap& expected_bitmap, | 517     SendCommand("Page.captureScreenshot", nullptr); | 
| 547                                      ScreenshotEncoding encoding) { |  | 
| 548     std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue()); |  | 
| 549     params->SetString("format", encoding == ENCODING_PNG ? "png" : "jpeg"); |  | 
| 550     params->SetInteger("quality", 100); |  | 
| 551     SendCommand("Page.captureScreenshot", std::move(params)); |  | 
| 552 |  | 
| 553     std::string base64; | 518     std::string base64; | 
| 554     EXPECT_TRUE(result_->GetString("data", &base64)); | 519     EXPECT_TRUE(result_->GetString("data", &base64)); | 
| 555     std::unique_ptr<SkBitmap> result_bitmap; | 520     SkBitmap result_bitmap; | 
| 556     int error_limit = 0; | 521     EXPECT_TRUE(DecodePNG(base64, &result_bitmap)); | 
| 557     if (encoding == ENCODING_PNG) { |  | 
| 558       result_bitmap.reset(new SkBitmap()); |  | 
| 559       EXPECT_TRUE(DecodePNG(base64, result_bitmap.get())); |  | 
| 560     } else { |  | 
| 561       result_bitmap = DecodeJPEG(base64); |  | 
| 562       // Even with quality 100, jpeg isn't lossless. So, we allow some skew in |  | 
| 563       // pixel values. Not that this assumes that there is no skew in pixel |  | 
| 564       // positions, so will only work reliably if all pixels have equal values. |  | 
| 565       error_limit = 3; |  | 
| 566     } |  | 
| 567     EXPECT_TRUE(result_bitmap); |  | 
| 568 |  | 
| 569     gfx::Rect matching_mask(gfx::SkIRectToRect(expected_bitmap.bounds())); | 522     gfx::Rect matching_mask(gfx::SkIRectToRect(expected_bitmap.bounds())); | 
| 570 #if defined(OS_MACOSX) | 523 #if defined(OS_MACOSX) | 
| 571     // Mask out the corners, which may be drawn differently on Mac because of | 524     // Mask out the corners, which may be drawn differently on Mac because of | 
| 572     // rounded corners. | 525     // rounded corners. | 
| 573     matching_mask.Inset(4, 4, 4, 4); | 526     matching_mask.Inset(4, 4, 4, 4); | 
| 574 #endif | 527 #endif | 
| 575     EXPECT_TRUE(MatchesBitmap(expected_bitmap, *result_bitmap, matching_mask, | 528     EXPECT_TRUE(MatchesBitmap(expected_bitmap, result_bitmap, matching_mask)); | 
| 576                               error_limit)); |  | 
| 577   } | 529   } | 
| 578 | 530 | 
| 579   // Takes a screenshot of a colored box that is positioned inside the frame. | 531   // Takes a screenshot of a colored box that is positioned inside the frame. | 
| 580   void PlaceAndCaptureBox(const gfx::Size& frame_size, | 532   void PlaceAndCaptureBox(const gfx::Size& frame_size, | 
| 581                           const gfx::Size& box_size, | 533                           const gfx::Size& box_size, | 
| 582                           float screenshot_scale) { | 534                           float screenshot_scale) { | 
| 583     static const int kBoxOffsetHeight = 100; | 535     static const int kBoxOffsetHeight = 100; | 
| 584     const gfx::Size scaled_box_size = | 536     const gfx::Size scaled_box_size = | 
| 585         ScaleToFlooredSize(box_size, screenshot_scale); | 537         ScaleToFlooredSize(box_size, screenshot_scale); | 
| 586     std::unique_ptr<base::DictionaryValue> params; | 538     std::unique_ptr<base::DictionaryValue> params; | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 625     params->SetDouble("x", (frame_size.width() - box_size.width()) / 2.); | 577     params->SetDouble("x", (frame_size.width() - box_size.width()) / 2.); | 
| 626     params->SetDouble("y", kBoxOffsetHeight); | 578     params->SetDouble("y", kBoxOffsetHeight); | 
| 627     params->SetDouble("scale", screenshot_scale); | 579     params->SetDouble("scale", screenshot_scale); | 
| 628     SendCommand("Emulation.forceViewport", std::move(params)); | 580     SendCommand("Emulation.forceViewport", std::move(params)); | 
| 629 | 581 | 
| 630     // Capture screenshot and verify that it is indeed blue. | 582     // Capture screenshot and verify that it is indeed blue. | 
| 631     SkBitmap expected_bitmap; | 583     SkBitmap expected_bitmap; | 
| 632     expected_bitmap.allocN32Pixels(scaled_box_size.width(), | 584     expected_bitmap.allocN32Pixels(scaled_box_size.width(), | 
| 633                                    scaled_box_size.height()); | 585                                    scaled_box_size.height()); | 
| 634     expected_bitmap.eraseColor(SkColorSetRGB(0x00, 0x00, 0xff)); | 586     expected_bitmap.eraseColor(SkColorSetRGB(0x00, 0x00, 0xff)); | 
| 635     CaptureScreenshotAndCompareTo(expected_bitmap, ENCODING_PNG); | 587     CaptureScreenshotAndCompareTo(expected_bitmap); | 
| 636 | 588 | 
| 637     // Reset for next screenshot. | 589     // Reset for next screenshot. | 
| 638     SendCommand("Emulation.resetViewport", nullptr); | 590     SendCommand("Emulation.resetViewport", nullptr); | 
| 639     SendCommand("Emulation.clearDeviceMetricsOverride", nullptr); | 591     SendCommand("Emulation.clearDeviceMetricsOverride", nullptr); | 
| 640   } | 592   } | 
| 641 | 593 | 
| 642  private: | 594  private: | 
| 643 #if !defined(OS_ANDROID) | 595 #if !defined(OS_ANDROID) | 
| 644   void SetUpCommandLine(base::CommandLine* command_line) override { | 596   void SetUpCommandLine(base::CommandLine* command_line) override { | 
| 645     command_line->AppendSwitch(switches::kEnablePixelOutputInTests); | 597     command_line->AppendSwitch(switches::kEnablePixelOutputInTests); | 
| 646   } | 598   } | 
| 647 #endif | 599 #endif | 
| 648 }; | 600 }; | 
| 649 | 601 | 
| 650 IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, CaptureScreenshot) { | 602 IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, CaptureScreenshot) { | 
| 651   // This test fails consistently on low-end Android devices. | 603   // This test fails consistently on low-end Android devices. | 
| 652   // See crbug.com/653637. | 604   // See crbug.com/653637. | 
| 653   // TODO(eseckler): Reenable with error limit if necessary. |  | 
| 654   if (base::SysInfo::IsLowEndDevice()) return; | 605   if (base::SysInfo::IsLowEndDevice()) return; | 
| 655 | 606 | 
| 656   shell()->LoadURL( | 607   shell()->LoadURL(GURL("about:blank")); | 
| 657       GURL("data:text/html,<body style='background:#123456'></body>")); |  | 
| 658   WaitForLoadStop(shell()->web_contents()); |  | 
| 659   Attach(); | 608   Attach(); | 
|  | 609   EXPECT_TRUE( | 
|  | 610       content::ExecuteScript(shell()->web_contents()->GetRenderViewHost(), | 
|  | 611                              "document.body.style.background = '#123456'")); | 
| 660   SkBitmap expected_bitmap; | 612   SkBitmap expected_bitmap; | 
| 661   // We compare against the actual physical backing size rather than the | 613   // We compare against the actual physical backing size rather than the | 
| 662   // view size, because the view size is stored adjusted for DPI and only in | 614   // view size, because the view size is stored adjusted for DPI and only in | 
| 663   // integer precision. | 615   // integer precision. | 
| 664   gfx::Size view_size = static_cast<RenderWidgetHostViewBase*>( | 616   gfx::Size view_size = static_cast<RenderWidgetHostViewBase*>( | 
| 665                             shell()->web_contents()->GetRenderWidgetHostView()) | 617                             shell()->web_contents()->GetRenderWidgetHostView()) | 
| 666                             ->GetPhysicalBackingSize(); | 618                             ->GetPhysicalBackingSize(); | 
| 667   expected_bitmap.allocN32Pixels(view_size.width(), view_size.height()); | 619   expected_bitmap.allocN32Pixels(view_size.width(), view_size.height()); | 
| 668   expected_bitmap.eraseColor(SkColorSetRGB(0x12, 0x34, 0x56)); | 620   expected_bitmap.eraseColor(SkColorSetRGB(0x12, 0x34, 0x56)); | 
| 669   CaptureScreenshotAndCompareTo(expected_bitmap, ENCODING_PNG); | 621   CaptureScreenshotAndCompareTo(expected_bitmap); | 
| 670 } |  | 
| 671 |  | 
| 672 IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, CaptureScreenshotJpeg) { |  | 
| 673   // This test fails consistently on low-end Android devices. |  | 
| 674   // See crbug.com/653637. |  | 
| 675   // TODO(eseckler): Reenable with error limit if necessary. |  | 
| 676   if (base::SysInfo::IsLowEndDevice()) |  | 
| 677     return; |  | 
| 678 |  | 
| 679   shell()->LoadURL( |  | 
| 680       GURL("data:text/html,<body style='background:#123456'></body>")); |  | 
| 681   WaitForLoadStop(shell()->web_contents()); |  | 
| 682   Attach(); |  | 
| 683   SkBitmap expected_bitmap; |  | 
| 684   // We compare against the actual physical backing size rather than the |  | 
| 685   // view size, because the view size is stored adjusted for DPI and only in |  | 
| 686   // integer precision. |  | 
| 687   gfx::Size view_size = static_cast<RenderWidgetHostViewBase*>( |  | 
| 688                             shell()->web_contents()->GetRenderWidgetHostView()) |  | 
| 689                             ->GetPhysicalBackingSize(); |  | 
| 690   expected_bitmap.allocN32Pixels(view_size.width(), view_size.height()); |  | 
| 691   expected_bitmap.eraseColor(SkColorSetRGB(0x12, 0x34, 0x56)); |  | 
| 692   CaptureScreenshotAndCompareTo(expected_bitmap, ENCODING_JPEG); |  | 
| 693 } | 622 } | 
| 694 | 623 | 
| 695 // Setting frame size (through RWHV) is not supported on Android. | 624 // Setting frame size (through RWHV) is not supported on Android. | 
| 696 #if defined(OS_ANDROID) | 625 #if defined(OS_ANDROID) | 
| 697 #define MAYBE_CaptureScreenshotArea DISABLED_CaptureScreenshotArea | 626 #define MAYBE_CaptureScreenshotArea DISABLED_CaptureScreenshotArea | 
| 698 #else | 627 #else | 
| 699 #define MAYBE_CaptureScreenshotArea CaptureScreenshotArea | 628 #define MAYBE_CaptureScreenshotArea CaptureScreenshotArea | 
| 700 #endif | 629 #endif | 
| 701 IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, | 630 IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, | 
| 702                        MAYBE_CaptureScreenshotArea) { | 631                        MAYBE_CaptureScreenshotArea) { | 
| (...skipping 875 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1578       EXPECT_EQ("polyglottal", value); | 1507       EXPECT_EQ("polyglottal", value); | 
| 1579       found++; | 1508       found++; | 
| 1580     } else { | 1509     } else { | 
| 1581       FAIL(); | 1510       FAIL(); | 
| 1582     } | 1511     } | 
| 1583   } | 1512   } | 
| 1584   EXPECT_EQ(2u, found); | 1513   EXPECT_EQ(2u, found); | 
| 1585 } | 1514 } | 
| 1586 | 1515 | 
| 1587 }  // namespace content | 1516 }  // namespace content | 
| OLD | NEW | 
|---|