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

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

Issue 2592983002: [devtools] Support different encodings for Page.CaptureScreenshot. (Closed)
Patch Set: Wait for load in CaptureScreenshotTest to fix android bot. Created 3 years, 11 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 unified diff | Download patch
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...) Expand 10 before | Expand all | Expand 10 after
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 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
457 namespace { 459 namespace {
458 bool DecodePNG(std::string base64_data, SkBitmap* bitmap) { 460 bool DecodePNG(std::string base64_data, SkBitmap* bitmap) {
459 std::string png_data; 461 std::string png_data;
460 if (!base::Base64Decode(base64_data, &png_data)) 462 if (!base::Base64Decode(base64_data, &png_data))
461 return false; 463 return false;
462 return gfx::PNGCodec::Decode( 464 return gfx::PNGCodec::Decode(
463 reinterpret_cast<unsigned const char*>(png_data.data()), png_data.size(), 465 reinterpret_cast<unsigned const char*>(png_data.data()), png_data.size(),
464 bitmap); 466 bitmap);
465 } 467 }
466 468
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
467 // Adapted from cc::ExactPixelComparator. 478 // Adapted from cc::ExactPixelComparator.
468 bool MatchesBitmap(const SkBitmap& expected_bmp, 479 bool MatchesBitmap(const SkBitmap& expected_bmp,
469 const SkBitmap& actual_bmp, 480 const SkBitmap& actual_bmp,
470 const gfx::Rect& matching_mask) { 481 const gfx::Rect& matching_mask,
482 int error_limit) {
471 // Number of pixels with an error 483 // Number of pixels with an error
472 int error_pixels_count = 0; 484 int error_pixels_count = 0;
473 485
474 gfx::Rect error_bounding_rect = gfx::Rect(); 486 gfx::Rect error_bounding_rect = gfx::Rect();
475 487
476 // Check that bitmaps have identical dimensions. 488 // Check that bitmaps have identical dimensions.
477 EXPECT_EQ(expected_bmp.width(), actual_bmp.width()); 489 EXPECT_EQ(expected_bmp.width(), actual_bmp.width());
478 EXPECT_EQ(expected_bmp.height(), actual_bmp.height()); 490 EXPECT_EQ(expected_bmp.height(), actual_bmp.height());
479 if (expected_bmp.width() != actual_bmp.width() || 491 if (expected_bmp.width() != actual_bmp.width() ||
480 expected_bmp.height() != actual_bmp.height()) { 492 expected_bmp.height() != actual_bmp.height()) {
481 return false; 493 return false;
482 } 494 }
483 495
484 SkAutoLockPixels lock_actual_bmp(actual_bmp); 496 SkAutoLockPixels lock_actual_bmp(actual_bmp);
485 SkAutoLockPixels lock_expected_bmp(expected_bmp); 497 SkAutoLockPixels lock_expected_bmp(expected_bmp);
486 498
487 DCHECK(gfx::SkIRectToRect(actual_bmp.bounds()).Contains(matching_mask)); 499 DCHECK(gfx::SkIRectToRect(actual_bmp.bounds()).Contains(matching_mask));
488 500
489 for (int x = matching_mask.x(); x < matching_mask.width(); ++x) { 501 for (int x = matching_mask.x(); x < matching_mask.width(); ++x) {
490 for (int y = matching_mask.y(); y < matching_mask.height(); ++y) { 502 for (int y = matching_mask.y(); y < matching_mask.height(); ++y) {
491 SkColor actual_color = actual_bmp.getColor(x, y); 503 SkColor actual_color = actual_bmp.getColor(x, y);
492 SkColor expected_color = expected_bmp.getColor(x, y); 504 SkColor expected_color = expected_bmp.getColor(x, y);
493 if (actual_color != expected_color) { 505 if (std::abs(static_cast<int32_t>(actual_color) -
506 static_cast<int32_t>(expected_color)) > error_limit) {
Avi (use Gerrit) 2017/01/09 16:57:33 An SkColor is a set of four 8-bit values packed in
Eric Seckler 2017/01/11 15:58:44 Uhh, yeah. Wasn't thinking here. Thank you for the
494 if (error_pixels_count < 10) { 507 if (error_pixels_count < 10) {
495 LOG(ERROR) << "Pixel (" << x << "," << y << "): expected " 508 LOG(ERROR) << "Pixel (" << x << "," << y << "): expected "
496 << expected_color << " actual " << actual_color; 509 << expected_color << " actual " << actual_color;
497 } 510 }
498 error_pixels_count++; 511 error_pixels_count++;
499 error_bounding_rect.Union(gfx::Rect(x, y, 1, 1)); 512 error_bounding_rect.Union(gfx::Rect(x, y, 1, 1));
500 } 513 }
501 } 514 }
502 } 515 }
503 516
504 if (error_pixels_count != 0) { 517 if (error_pixels_count != 0) {
505 LOG(ERROR) << "Number of pixel with an error: " << error_pixels_count; 518 LOG(ERROR) << "Number of pixel with an error: " << error_pixels_count;
506 LOG(ERROR) << "Error Bounding Box : " << error_bounding_rect.ToString(); 519 LOG(ERROR) << "Error Bounding Box : " << error_bounding_rect.ToString();
507 return false; 520 return false;
508 } 521 }
509 522
510 return true; 523 return true;
511 } 524 }
512 } // namespace 525 } // namespace
513 526
514 class CaptureScreenshotTest : public DevToolsProtocolTest { 527 class CaptureScreenshotTest : public DevToolsProtocolTest {
515 protected: 528 protected:
516 void CaptureScreenshotAndCompareTo(const SkBitmap& expected_bitmap) { 529 enum ScreenshotEncoding { ENCODING_PNG, ENCODING_JPEG };
517 SendCommand("Page.captureScreenshot", nullptr); 530 void CaptureScreenshotAndCompareTo(const SkBitmap& expected_bitmap,
531 ScreenshotEncoding encoding) {
532 std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
533 params->SetString("format", encoding == ENCODING_PNG ? "png" : "jpeg");
534 params->SetInteger("quality", 100);
535 SendCommand("Page.captureScreenshot", std::move(params));
536
518 std::string base64; 537 std::string base64;
519 EXPECT_TRUE(result_->GetString("data", &base64)); 538 EXPECT_TRUE(result_->GetString("data", &base64));
520 SkBitmap result_bitmap; 539 std::unique_ptr<SkBitmap> result_bitmap;
521 EXPECT_TRUE(DecodePNG(base64, &result_bitmap)); 540 int error_limit = 0;
541 if (encoding == ENCODING_PNG) {
542 result_bitmap.reset(new SkBitmap());
543 EXPECT_TRUE(DecodePNG(base64, result_bitmap.get()));
544 } else {
545 result_bitmap = DecodeJPEG(base64);
546 // Even with quality 100, jpeg isn't lossless. So, we allow some skew in
547 // pixel values. Not that this assumes that there is no skew in pixel
548 // positions, so will only work reliably if all pixels have equal values.
549 error_limit = 3;
550 }
551 EXPECT_TRUE(result_bitmap);
552
522 gfx::Rect matching_mask(gfx::SkIRectToRect(expected_bitmap.bounds())); 553 gfx::Rect matching_mask(gfx::SkIRectToRect(expected_bitmap.bounds()));
523 #if defined(OS_MACOSX) 554 #if defined(OS_MACOSX)
524 // Mask out the corners, which may be drawn differently on Mac because of 555 // Mask out the corners, which may be drawn differently on Mac because of
525 // rounded corners. 556 // rounded corners.
526 matching_mask.Inset(4, 4, 4, 4); 557 matching_mask.Inset(4, 4, 4, 4);
527 #endif 558 #endif
528 EXPECT_TRUE(MatchesBitmap(expected_bitmap, result_bitmap, matching_mask)); 559 EXPECT_TRUE(MatchesBitmap(expected_bitmap, *result_bitmap, matching_mask,
560 error_limit));
529 } 561 }
530 562
531 // Takes a screenshot of a colored box that is positioned inside the frame. 563 // Takes a screenshot of a colored box that is positioned inside the frame.
532 void PlaceAndCaptureBox(const gfx::Size& frame_size, 564 void PlaceAndCaptureBox(const gfx::Size& frame_size,
533 const gfx::Size& box_size, 565 const gfx::Size& box_size,
534 float screenshot_scale) { 566 float screenshot_scale) {
535 static const int kBoxOffsetHeight = 100; 567 static const int kBoxOffsetHeight = 100;
536 const gfx::Size scaled_box_size = 568 const gfx::Size scaled_box_size =
537 ScaleToFlooredSize(box_size, screenshot_scale); 569 ScaleToFlooredSize(box_size, screenshot_scale);
538 std::unique_ptr<base::DictionaryValue> params; 570 std::unique_ptr<base::DictionaryValue> params;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
577 params->SetDouble("x", (frame_size.width() - box_size.width()) / 2.); 609 params->SetDouble("x", (frame_size.width() - box_size.width()) / 2.);
578 params->SetDouble("y", kBoxOffsetHeight); 610 params->SetDouble("y", kBoxOffsetHeight);
579 params->SetDouble("scale", screenshot_scale); 611 params->SetDouble("scale", screenshot_scale);
580 SendCommand("Emulation.forceViewport", std::move(params)); 612 SendCommand("Emulation.forceViewport", std::move(params));
581 613
582 // Capture screenshot and verify that it is indeed blue. 614 // Capture screenshot and verify that it is indeed blue.
583 SkBitmap expected_bitmap; 615 SkBitmap expected_bitmap;
584 expected_bitmap.allocN32Pixels(scaled_box_size.width(), 616 expected_bitmap.allocN32Pixels(scaled_box_size.width(),
585 scaled_box_size.height()); 617 scaled_box_size.height());
586 expected_bitmap.eraseColor(SkColorSetRGB(0x00, 0x00, 0xff)); 618 expected_bitmap.eraseColor(SkColorSetRGB(0x00, 0x00, 0xff));
587 CaptureScreenshotAndCompareTo(expected_bitmap); 619 CaptureScreenshotAndCompareTo(expected_bitmap, ENCODING_PNG);
588 620
589 // Reset for next screenshot. 621 // Reset for next screenshot.
590 SendCommand("Emulation.resetViewport", nullptr); 622 SendCommand("Emulation.resetViewport", nullptr);
591 SendCommand("Emulation.clearDeviceMetricsOverride", nullptr); 623 SendCommand("Emulation.clearDeviceMetricsOverride", nullptr);
592 } 624 }
593 625
594 private: 626 private:
595 #if !defined(OS_ANDROID) 627 #if !defined(OS_ANDROID)
596 void SetUpCommandLine(base::CommandLine* command_line) override { 628 void SetUpCommandLine(base::CommandLine* command_line) override {
597 command_line->AppendSwitch(switches::kEnablePixelOutputInTests); 629 command_line->AppendSwitch(switches::kEnablePixelOutputInTests);
598 } 630 }
599 #endif 631 #endif
600 }; 632 };
601 633
602 IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, CaptureScreenshot) { 634 IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, CaptureScreenshot) {
603 // This test fails consistently on low-end Android devices. 635 // This test fails consistently on low-end Android devices.
604 // See crbug.com/653637. 636 // See crbug.com/653637.
605 if (base::SysInfo::IsLowEndDevice()) return; 637 if (base::SysInfo::IsLowEndDevice()) return;
606 638
607 shell()->LoadURL(GURL("about:blank")); 639 shell()->LoadURL(
640 GURL("data:text/html,<body style='background:#123456'></body>"));
641 WaitForLoadStop(shell()->web_contents());
608 Attach(); 642 Attach();
609 EXPECT_TRUE(
610 content::ExecuteScript(shell()->web_contents()->GetRenderViewHost(),
611 "document.body.style.background = '#123456'"));
612 SkBitmap expected_bitmap; 643 SkBitmap expected_bitmap;
613 // We compare against the actual physical backing size rather than the 644 // We compare against the actual physical backing size rather than the
614 // view size, because the view size is stored adjusted for DPI and only in 645 // view size, because the view size is stored adjusted for DPI and only in
646 // integer precision.
647 gfx::Size view_size = static_cast<RenderWidgetHostViewBase*>(
648 shell()->web_contents()->GetRenderWidgetHostView())
649 ->GetPhysicalBackingSize();
650 expected_bitmap.allocN32Pixels(view_size.width(), view_size.height());
651 expected_bitmap.eraseColor(SkColorSetRGB(0x12, 0x34, 0x56));
652 CaptureScreenshotAndCompareTo(expected_bitmap, ENCODING_PNG);
653 }
654
655 IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, CaptureScreenshotJpeg) {
656 // This test fails consistently on low-end Android devices.
657 // See crbug.com/653637.
Avi (use Gerrit) 2017/01/09 16:57:33 This bug is about mismatches in color. Do we want
Eric Seckler 2017/01/11 15:58:44 I'm actually not sure if this would still be happe
Avi (use Gerrit) 2017/01/11 17:09:20 SGTM!
658 if (base::SysInfo::IsLowEndDevice())
659 return;
660
661 shell()->LoadURL(
662 GURL("data:text/html,<body style='background:#123456'></body>"));
663 WaitForLoadStop(shell()->web_contents());
664 Attach();
665 SkBitmap expected_bitmap;
666 // We compare against the actual physical backing size rather than the
667 // view size, because the view size is stored adjusted for DPI and only in
615 // integer precision. 668 // integer precision.
616 gfx::Size view_size = static_cast<RenderWidgetHostViewBase*>( 669 gfx::Size view_size = static_cast<RenderWidgetHostViewBase*>(
617 shell()->web_contents()->GetRenderWidgetHostView()) 670 shell()->web_contents()->GetRenderWidgetHostView())
618 ->GetPhysicalBackingSize(); 671 ->GetPhysicalBackingSize();
619 expected_bitmap.allocN32Pixels(view_size.width(), view_size.height()); 672 expected_bitmap.allocN32Pixels(view_size.width(), view_size.height());
620 expected_bitmap.eraseColor(SkColorSetRGB(0x12, 0x34, 0x56)); 673 expected_bitmap.eraseColor(SkColorSetRGB(0x12, 0x34, 0x56));
621 CaptureScreenshotAndCompareTo(expected_bitmap); 674 CaptureScreenshotAndCompareTo(expected_bitmap, ENCODING_JPEG);
622 } 675 }
623 676
624 // Setting frame size (through RWHV) is not supported on Android. 677 // Setting frame size (through RWHV) is not supported on Android.
625 #if defined(OS_ANDROID) 678 #if defined(OS_ANDROID)
626 #define MAYBE_CaptureScreenshotArea DISABLED_CaptureScreenshotArea 679 #define MAYBE_CaptureScreenshotArea DISABLED_CaptureScreenshotArea
627 #else 680 #else
628 #define MAYBE_CaptureScreenshotArea CaptureScreenshotArea 681 #define MAYBE_CaptureScreenshotArea CaptureScreenshotArea
629 #endif 682 #endif
630 IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, 683 IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest,
631 MAYBE_CaptureScreenshotArea) { 684 MAYBE_CaptureScreenshotArea) {
(...skipping 875 matching lines...) Expand 10 before | Expand all | Expand 10 after
1507 EXPECT_EQ("polyglottal", value); 1560 EXPECT_EQ("polyglottal", value);
1508 found++; 1561 found++;
1509 } else { 1562 } else {
1510 FAIL(); 1563 FAIL();
1511 } 1564 }
1512 } 1565 }
1513 EXPECT_EQ(2u, found); 1566 EXPECT_EQ(2u, found);
1514 } 1567 }
1515 1568
1516 } // namespace content 1569 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698