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

Side by Side 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, 2 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
10 #include "base/bind_helpers.h"
9 #include "base/command_line.h" 11 #include "base/command_line.h"
10 #include "base/json/json_reader.h" 12 #include "base/json/json_reader.h"
11 #include "base/json/json_writer.h" 13 #include "base/json/json_writer.h"
14 #include "base/logging.h"
12 #include "base/memory/ptr_util.h" 15 #include "base/memory/ptr_util.h"
13 #include "base/run_loop.h" 16 #include "base/run_loop.h"
17 #include "base/strings/stringprintf.h"
14 #include "base/strings/utf_string_conversions.h" 18 #include "base/strings/utf_string_conversions.h"
15 #include "base/values.h" 19 #include "base/values.h"
16 #include "build/build_config.h" 20 #include "build/build_config.h"
17 #include "content/browser/frame_host/interstitial_page_impl.h" 21 #include "content/browser/frame_host/interstitial_page_impl.h"
22 #include "content/browser/renderer_host/render_widget_host_view_base.h"
18 #include "content/browser/web_contents/web_contents_impl.h" 23 #include "content/browser/web_contents/web_contents_impl.h"
19 #include "content/public/browser/devtools_agent_host.h" 24 #include "content/public/browser/devtools_agent_host.h"
20 #include "content/public/browser/interstitial_page_delegate.h" 25 #include "content/public/browser/interstitial_page_delegate.h"
21 #include "content/public/browser/javascript_dialog_manager.h" 26 #include "content/public/browser/javascript_dialog_manager.h"
22 #include "content/public/browser/navigation_controller.h" 27 #include "content/public/browser/navigation_controller.h"
23 #include "content/public/browser/navigation_entry.h" 28 #include "content/public/browser/navigation_entry.h"
24 #include "content/public/browser/navigation_handle.h" 29 #include "content/public/browser/navigation_handle.h"
25 #include "content/public/browser/render_frame_host.h" 30 #include "content/public/browser/render_frame_host.h"
26 #include "content/public/browser/render_view_host.h" 31 #include "content/public/browser/render_view_host.h"
27 #include "content/public/browser/render_widget_host_view.h" 32 #include "content/public/browser/render_widget_host_view.h"
28 #include "content/public/browser/ssl_status.h" 33 #include "content/public/browser/ssl_status.h"
29 #include "content/public/browser/web_contents.h" 34 #include "content/public/browser/web_contents.h"
30 #include "content/public/common/url_constants.h" 35 #include "content/public/common/url_constants.h"
31 #include "content/public/test/browser_test_utils.h" 36 #include "content/public/test/browser_test_utils.h"
32 #include "content/public/test/content_browser_test.h" 37 #include "content/public/test/content_browser_test.h"
33 #include "content/public/test/content_browser_test_utils.h" 38 #include "content/public/test/content_browser_test_utils.h"
34 #include "content/public/test/test_navigation_observer.h" 39 #include "content/public/test/test_navigation_observer.h"
35 #include "content/shell/browser/shell.h" 40 #include "content/shell/browser/shell.h"
36 #include "net/dns/mock_host_resolver.h" 41 #include "net/dns/mock_host_resolver.h"
37 #include "net/test/cert_test_util.h" 42 #include "net/test/cert_test_util.h"
38 #include "net/test/embedded_test_server/embedded_test_server.h" 43 #include "net/test/embedded_test_server/embedded_test_server.h"
39 #include "net/test/test_data_directory.h" 44 #include "net/test/test_data_directory.h"
40 #include "testing/gmock/include/gmock/gmock.h" 45 #include "testing/gmock/include/gmock/gmock.h"
41 #include "third_party/skia/include/core/SkBitmap.h" 46 #include "third_party/skia/include/core/SkBitmap.h"
47 #include "third_party/skia/include/core/SkColor.h"
48 #include "ui/base/layout.h"
42 #include "ui/compositor/compositor_switches.h" 49 #include "ui/compositor/compositor_switches.h"
43 #include "ui/gfx/codec/png_codec.h" 50 #include "ui/gfx/codec/png_codec.h"
51 #include "ui/gfx/geometry/rect.h"
52 #include "ui/gfx/geometry/size.h"
53 #include "ui/gfx/skia_util.h"
44 54
45 #define EXPECT_SIZE_EQ(expected, actual) \ 55 #define EXPECT_SIZE_EQ(expected, actual) \
46 do { \ 56 do { \
47 EXPECT_EQ((expected).width(), (actual).width()); \ 57 EXPECT_EQ((expected).width(), (actual).width()); \
48 EXPECT_EQ((expected).height(), (actual).height()); \ 58 EXPECT_EQ((expected).height(), (actual).height()); \
49 } while (false) 59 } while (false)
50 60
51 using testing::ElementsAre; 61 using testing::ElementsAre;
52 62
53 namespace content { 63 namespace content {
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 // Send escape (keycode 27). 419 // Send escape (keycode 27).
410 SendKeyEvent("rawKeyDown", 0, 27, 27, "Escape"); 420 SendKeyEvent("rawKeyDown", 0, 27, 27, "Escape");
411 SendKeyEvent("keyUp", 0, 27, 27, "Escape"); 421 SendKeyEvent("keyUp", 0, 27, 27, "Escape");
412 422
413 ASSERT_TRUE(dom_message_queue.WaitForMessage(&key)); 423 ASSERT_TRUE(dom_message_queue.WaitForMessage(&key));
414 EXPECT_EQ("\"Escape\"", key); 424 EXPECT_EQ("\"Escape\"", key);
415 ASSERT_TRUE(dom_message_queue.WaitForMessage(&key)); 425 ASSERT_TRUE(dom_message_queue.WaitForMessage(&key));
416 EXPECT_EQ("\"Escape\"", key); 426 EXPECT_EQ("\"Escape\"", key);
417 } 427 }
418 428
429 namespace {
430 bool DecodePNG(std::string base64_data, SkBitmap* bitmap) {
431 std::string png_data;
432 if (!base::Base64Decode(base64_data, &png_data))
433 return false;
434 return gfx::PNGCodec::Decode(
435 reinterpret_cast<unsigned const char*>(png_data.data()), png_data.size(),
436 bitmap);
437 }
438
439 // Adapted from cc::ExactPixelComparator.
440 bool MatchesBitmap(const SkBitmap& expected_bmp,
441 const SkBitmap& actual_bmp,
442 const gfx::Rect& matching_mask) {
443 // Number of pixels with an error
444 int error_pixels_count = 0;
445
446 gfx::Rect error_bounding_rect = gfx::Rect();
447
448 // Check that bitmaps have identical dimensions.
449 EXPECT_EQ(expected_bmp.width(), actual_bmp.width());
450 EXPECT_EQ(expected_bmp.height(), actual_bmp.height());
451 if (expected_bmp.width() != actual_bmp.width() ||
452 expected_bmp.height() != actual_bmp.height()) {
453 return false;
454 }
455
456 SkAutoLockPixels lock_actual_bmp(actual_bmp);
457 SkAutoLockPixels lock_expected_bmp(expected_bmp);
458
459 DCHECK(gfx::SkIRectToRect(actual_bmp.bounds()).Contains(matching_mask));
460
461 for (int x = matching_mask.x(); x < matching_mask.width(); ++x) {
462 for (int y = matching_mask.y(); y < matching_mask.height(); ++y) {
463 SkColor actual_color = actual_bmp.getColor(x, y);
464 SkColor expected_color = expected_bmp.getColor(x, y);
465 if (actual_color != expected_color) {
466 if (error_pixels_count < 10) {
467 LOG(ERROR) << "Pixel (" << x << "," << y << "): expected "
468 << expected_color << " actual " << actual_color;
469 }
470 error_pixels_count++;
471 error_bounding_rect.Union(gfx::Rect(x, y, 1, 1));
472 }
473 }
474 }
475
476 if (error_pixels_count != 0) {
477 LOG(ERROR) << "Number of pixel with an error: " << error_pixels_count;
478 LOG(ERROR) << "Error Bounding Box : " << error_bounding_rect.ToString();
479 return false;
480 }
481
482 return true;
483 }
484 } // namespace
485
419 class CaptureScreenshotTest : public DevToolsProtocolTest { 486 class CaptureScreenshotTest : public DevToolsProtocolTest {
487 protected:
488 void CaptureScreenshotAndCompareTo(const SkBitmap& expected_bitmap) {
489 SendCommand("Page.captureScreenshot", nullptr);
490 std::string base64;
491 EXPECT_TRUE(result_->GetString("data", &base64));
492 SkBitmap result_bitmap;
493 EXPECT_TRUE(DecodePNG(base64, &result_bitmap));
494 gfx::Rect matching_mask(gfx::SkIRectToRect(expected_bitmap.bounds()));
495 #if defined(OS_MACOSX)
496 // Mask out the corners, which may be drawn differently on Mac because of
497 // rounded corners.
498 matching_mask.Inset(4, 4, 4, 4);
499 #endif
500 EXPECT_TRUE(MatchesBitmap(expected_bitmap, result_bitmap, matching_mask));
501 }
502
503 // Takes a screenshot of a colored box that is positioned inside the frame.
504 void PlaceAndCaptureBox(const gfx::Size& frame_size,
505 const gfx::Size& box_size,
506 float screenshot_scale) {
507 static const int kBoxOffsetHeight = 100;
508 const gfx::Size scaled_box_size =
509 ScaleToFlooredSize(box_size, screenshot_scale);
510 std::unique_ptr<base::DictionaryValue> params;
511
512 VLOG(1) << "Testing screenshot of box with size " << box_size.width() << "x"
513 << box_size.height() << "px at scale " << screenshot_scale
514 << " ...";
515
516 // Draw a blue box of provided size in the horizontal center of the page.
517 EXPECT_TRUE(content::ExecuteScript(
518 shell()->web_contents()->GetRenderViewHost(),
519 base::StringPrintf(
520 "var style = document.body.style; "
521 "style.overflow = 'hidden'; "
522 "style.minHeight = '%dpx'; "
523 "style.backgroundImage = 'linear-gradient(#0000ff, #0000ff)'; "
524 "style.backgroundSize = '%dpx %dpx'; "
525 "style.backgroundPosition = '50%% %dpx'; "
526 "style.backgroundRepeat = 'no-repeat'; ",
527 box_size.height() + kBoxOffsetHeight, box_size.width(),
528 box_size.height(), kBoxOffsetHeight)));
529
530 // Force frame size: The offset of the blue box within the frame shouldn't
531 // change during screenshotting. This verifies that the page doesn't observe
532 // a change in frame size as a side effect of screenshotting.
533 params.reset(new base::DictionaryValue());
534 params->SetInteger("width", frame_size.width());
535 params->SetInteger("height", frame_size.height());
536 params->SetDouble("deviceScaleFactor", 0);
537 params->SetBoolean("mobile", false);
538 params->SetBoolean("fitWindow", false);
539 SendCommand("Emulation.setDeviceMetricsOverride", std::move(params));
540
541 // Resize frame to scaled blue box size.
542 params.reset(new base::DictionaryValue());
543 params->SetInteger("width", scaled_box_size.width());
544 params->SetInteger("height", scaled_box_size.height());
545 SendCommand("Emulation.setVisibleSize", std::move(params));
546
547 // Force viewport to match scaled blue box.
548 params.reset(new base::DictionaryValue());
549 params->SetDouble("x", (frame_size.width() - box_size.width()) / 2.);
550 params->SetDouble("y", kBoxOffsetHeight);
551 params->SetDouble("scale", screenshot_scale);
552 SendCommand("Emulation.forceViewport", std::move(params));
553
554 // Capture screenshot and verify that it is indeed blue.
555 SkBitmap expected_bitmap;
556 expected_bitmap.allocN32Pixels(scaled_box_size.width(),
557 scaled_box_size.height());
558 expected_bitmap.eraseColor(SkColorSetRGB(0x00, 0x00, 0xff));
559 CaptureScreenshotAndCompareTo(expected_bitmap);
560
561 // Reset for next screenshot.
562 SendCommand("Emulation.resetViewport", nullptr);
563 SendCommand("Emulation.clearDeviceMetricsOverride", nullptr);
564 }
565
420 private: 566 private:
421 #if !defined(OS_ANDROID) 567 #if !defined(OS_ANDROID)
422 void SetUpCommandLine(base::CommandLine* command_line) override { 568 void SetUpCommandLine(base::CommandLine* command_line) override {
423 command_line->AppendSwitch(switches::kEnablePixelOutputInTests); 569 command_line->AppendSwitch(switches::kEnablePixelOutputInTests);
424 } 570 }
425 #endif 571 #endif
426 }; 572 };
427 573
428 // Does not link on Android
429 #if !defined(OS_ANDROID)
430 IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, CaptureScreenshot) { 574 IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, CaptureScreenshot) {
431 shell()->LoadURL(GURL("about:blank")); 575 shell()->LoadURL(GURL("about:blank"));
432 Attach(); 576 Attach();
433 EXPECT_TRUE(content::ExecuteScript( 577 EXPECT_TRUE(
434 shell()->web_contents()->GetRenderViewHost(), 578 content::ExecuteScript(shell()->web_contents()->GetRenderViewHost(),
435 "document.body.style.background = '#123456'")); 579 "document.body.style.background = '#123456'"));
436 SendCommand("Page.captureScreenshot", nullptr); 580 SkBitmap expected_bitmap;
437 std::string base64; 581 // We compare against the actual physical backing size rather than the
438 EXPECT_TRUE(result_->GetString("data", &base64)); 582 // view size, because the view size is stored adjusted for DPI and only in
439 std::string png; 583 // integer precision.
440 EXPECT_TRUE(base::Base64Decode(base64, &png)); 584 gfx::Size view_size = static_cast<RenderWidgetHostViewBase*>(
441 SkBitmap bitmap; 585 shell()->web_contents()->GetRenderWidgetHostView())
442 gfx::PNGCodec::Decode(reinterpret_cast<const unsigned char*>(png.data()), 586 ->GetPhysicalBackingSize();
443 png.size(), &bitmap); 587 expected_bitmap.allocN32Pixels(view_size.width(), view_size.height());
444 SkColor color(bitmap.getColor(0, 0)); 588 expected_bitmap.eraseColor(SkColorSetRGB(0x12, 0x34, 0x56));
445 EXPECT_GE(1, std::abs(0x12-(int)SkColorGetR(color))); 589 CaptureScreenshotAndCompareTo(expected_bitmap);
446 EXPECT_GE(1, std::abs(0x34-(int)SkColorGetG(color)));
447 EXPECT_GE(1, std::abs(0x56-(int)SkColorGetB(color)));
448 color = bitmap.getColor(1, 1);
449 EXPECT_GE(1, std::abs(0x12-(int)SkColorGetR(color)));
450 EXPECT_GE(1, std::abs(0x34-(int)SkColorGetG(color)));
451 EXPECT_GE(1, std::abs(0x56-(int)SkColorGetB(color)));
452 } 590 }
591
592 // Setting frame size (through RWHV) is not supported on Android.
593 #if defined(OS_ANDROID)
594 #define MAYBE_CaptureScreenshotArea DISABLED_CaptureScreenshotArea
595 #else
596 #define MAYBE_CaptureScreenshotArea CaptureScreenshotArea
453 #endif 597 #endif
598 IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest,
599 MAYBE_CaptureScreenshotArea) {
600 static const gfx::Size kFrameSize(800, 600);
601
602 shell()->LoadURL(GURL("about:blank"));
603 Attach();
604
605 // Test capturing a subarea inside the emulated frame at different scales.
606 PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 1.0);
607 PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 2.0);
608 PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 0.5);
609
610 // Ensure that content outside the emulated frame is painted, too.
611 PlaceAndCaptureBox(kFrameSize, gfx::Size(10, 10000), 1.0);
612 }
454 613
455 #if defined(OS_ANDROID) 614 #if defined(OS_ANDROID)
456 // Disabled, see http://crbug.com/469947. 615 // Disabled, see http://crbug.com/469947.
457 IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, DISABLED_SynthesizePinchGesture) { 616 IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, DISABLED_SynthesizePinchGesture) {
458 GURL test_url = GetTestUrl("devtools", "synthetic_gesture_tests.html"); 617 GURL test_url = GetTestUrl("devtools", "synthetic_gesture_tests.html");
459 NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1); 618 NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
460 Attach(); 619 Attach();
461 620
462 int old_width; 621 int old_width;
463 ASSERT_TRUE(content::ExecuteScriptAndExtractInt( 622 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
(...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after
1026 ASSERT_TRUE(transient_entry); 1185 ASSERT_TRUE(transient_entry);
1027 transient_entry->GetSSL().certificate = expired_cert(); 1186 transient_entry->GetSSL().certificate = expired_cert();
1028 ASSERT_TRUE(transient_entry->GetSSL().certificate); 1187 ASSERT_TRUE(transient_entry->GetSSL().certificate);
1029 1188
1030 std::unique_ptr<base::DictionaryValue> params2(new base::DictionaryValue()); 1189 std::unique_ptr<base::DictionaryValue> params2(new base::DictionaryValue());
1031 SendCommand("Security.showCertificateViewer", std::move(params2), true); 1190 SendCommand("Security.showCertificateViewer", std::move(params2), true);
1032 EXPECT_EQ(transient_entry->GetSSL().certificate, last_shown_certificate()); 1191 EXPECT_EQ(transient_entry->GetSSL().certificate, last_shown_certificate());
1033 } 1192 }
1034 1193
1035 } // namespace content 1194 } // namespace content
OLDNEW
« 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