Ignore non-active fullscreen windows for shelf state.
[chromium-blink-merge.git] / content / browser / renderer_host / render_widget_host_view_browsertest.cc
blobc6cb8d61034801ab1b0339f96272013b17505f85
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/command_line.h"
6 #include "base/message_loop/message_loop_proxy.h"
7 #include "base/path_service.h"
8 #include "base/run_loop.h"
9 #include "content/browser/gpu/compositor_util.h"
10 #include "content/browser/gpu/gpu_data_manager_impl.h"
11 #include "content/browser/renderer_host/dip_util.h"
12 #include "content/browser/renderer_host/render_widget_host_impl.h"
13 #include "content/port/browser/render_widget_host_view_frame_subscriber.h"
14 #include "content/port/browser/render_widget_host_view_port.h"
15 #include "content/public/browser/gpu_data_manager.h"
16 #include "content/public/browser/render_view_host.h"
17 #include "content/public/browser/web_contents.h"
18 #include "content/public/common/content_paths.h"
19 #include "content/public/common/content_switches.h"
20 #include "content/public/common/url_constants.h"
21 #include "content/public/test/browser_test_utils.h"
22 #include "content/shell/browser/shell.h"
23 #include "content/test/content_browser_test.h"
24 #include "content/test/content_browser_test_utils.h"
25 #include "media/base/video_frame.h"
26 #include "media/filters/skcanvas_video_renderer.h"
27 #include "net/base/net_util.h"
28 #include "third_party/skia/include/core/SkBitmap.h"
29 #include "third_party/skia/include/core/SkBitmapDevice.h"
30 #include "third_party/skia/include/core/SkCanvas.h"
31 #include "ui/base/ui_base_switches.h"
32 #include "ui/gfx/size_conversions.h"
33 #include "ui/gfx/switches.h"
34 #include "ui/gl/gl_switches.h"
36 #if defined(OS_MACOSX)
37 #include "ui/gl/io_surface_support_mac.h"
38 #endif
40 #if defined(OS_WIN)
41 #include "base/win/windows_version.h"
42 #include "ui/gfx/win/dpi.h"
43 #endif
45 namespace content {
46 namespace {
48 // Convenience macro: Short-circuit a pass for the tests where platform support
49 // for forced-compositing mode (or disabled-compositing mode) is lacking.
50 #define SET_UP_SURFACE_OR_PASS_TEST(wait_message) \
51 if (!SetUpSourceSurface(wait_message)) { \
52 LOG(WARNING) \
53 << ("Blindly passing this test: This platform does not support " \
54 "forced compositing (or forced-disabled compositing) mode."); \
55 return; \
58 // Convenience macro: Short-circuit a pass for platforms where setting up
59 // high-DPI fails.
60 #define PASS_TEST_IF_SCALE_FACTOR_NOT_SUPPORTED(factor) \
61 if (ui::GetImageScale( \
62 GetScaleFactorForView(GetRenderWidgetHostViewPort())) != factor) { \
63 LOG(WARNING) << "Blindly passing this test: failed to set up " \
64 "scale factor: " << factor; \
65 return false; \
68 // Common base class for browser tests. This is subclassed twice: Once to test
69 // the browser in forced-compositing mode, and once to test with compositing
70 // mode disabled.
71 class RenderWidgetHostViewBrowserTest : public ContentBrowserTest {
72 public:
73 RenderWidgetHostViewBrowserTest()
74 : frame_size_(400, 300),
75 callback_invoke_count_(0),
76 frames_captured_(0) {}
78 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
79 ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &test_dir_));
80 ContentBrowserTest::SetUpInProcessBrowserTestFixture();
83 // Attempts to set up the source surface. Returns false if unsupported on the
84 // current platform.
85 virtual bool SetUpSourceSurface(const char* wait_message) = 0;
87 int callback_invoke_count() const {
88 return callback_invoke_count_;
91 int frames_captured() const {
92 return frames_captured_;
95 const gfx::Size& frame_size() const {
96 return frame_size_;
99 const base::FilePath& test_dir() const {
100 return test_dir_;
103 RenderViewHost* GetRenderViewHost() const {
104 RenderViewHost* const rvh = shell()->web_contents()->GetRenderViewHost();
105 CHECK(rvh);
106 return rvh;
109 RenderWidgetHostImpl* GetRenderWidgetHost() const {
110 RenderWidgetHostImpl* const rwh = RenderWidgetHostImpl::From(
111 shell()->web_contents()->GetRenderWidgetHostView()->
112 GetRenderWidgetHost());
113 CHECK(rwh);
114 return rwh;
117 RenderWidgetHostViewPort* GetRenderWidgetHostViewPort() const {
118 RenderWidgetHostViewPort* const view =
119 RenderWidgetHostViewPort::FromRWHV(GetRenderViewHost()->GetView());
120 CHECK(view);
121 return view;
124 // Callback when using CopyFromBackingStore() API.
125 void FinishCopyFromBackingStore(const base::Closure& quit_closure,
126 bool frame_captured,
127 const SkBitmap& bitmap) {
128 ++callback_invoke_count_;
129 if (frame_captured) {
130 ++frames_captured_;
131 EXPECT_FALSE(bitmap.empty());
133 if (!quit_closure.is_null())
134 quit_closure.Run();
137 // Callback when using CopyFromCompositingSurfaceToVideoFrame() API.
138 void FinishCopyFromCompositingSurface(const base::Closure& quit_closure,
139 bool frame_captured) {
140 ++callback_invoke_count_;
141 if (frame_captured)
142 ++frames_captured_;
143 if (!quit_closure.is_null())
144 quit_closure.Run();
147 // Callback when using frame subscriber API.
148 void FrameDelivered(const scoped_refptr<base::MessageLoopProxy>& loop,
149 base::Closure quit_closure,
150 base::Time timestamp,
151 bool frame_captured) {
152 ++callback_invoke_count_;
153 if (frame_captured)
154 ++frames_captured_;
155 if (!quit_closure.is_null())
156 loop->PostTask(FROM_HERE, quit_closure);
159 // Copy one frame using the CopyFromBackingStore API.
160 void RunBasicCopyFromBackingStoreTest() {
161 SET_UP_SURFACE_OR_PASS_TEST(NULL);
163 // Repeatedly call CopyFromBackingStore() since, on some platforms (e.g.,
164 // Windows), the operation will fail until the first "present" has been
165 // made.
166 int count_attempts = 0;
167 while (true) {
168 ++count_attempts;
169 base::RunLoop run_loop;
170 GetRenderViewHost()->CopyFromBackingStore(
171 gfx::Rect(),
172 frame_size(),
173 base::Bind(
174 &RenderWidgetHostViewBrowserTest::FinishCopyFromBackingStore,
175 base::Unretained(this),
176 run_loop.QuitClosure()));
177 run_loop.Run();
179 if (frames_captured())
180 break;
181 else
182 GiveItSomeTime();
185 EXPECT_EQ(count_attempts, callback_invoke_count());
186 EXPECT_EQ(1, frames_captured());
189 protected:
190 // Waits until the source is available for copying.
191 void WaitForCopySourceReady() {
192 while (!GetRenderWidgetHostViewPort()->IsSurfaceAvailableForCopy())
193 GiveItSomeTime();
196 // Run the current message loop for a short time without unwinding the current
197 // call stack.
198 static void GiveItSomeTime() {
199 base::RunLoop run_loop;
200 base::MessageLoop::current()->PostDelayedTask(
201 FROM_HERE,
202 run_loop.QuitClosure(),
203 base::TimeDelta::FromMilliseconds(10));
204 run_loop.Run();
207 private:
208 const gfx::Size frame_size_;
209 base::FilePath test_dir_;
210 int callback_invoke_count_;
211 int frames_captured_;
214 class CompositingRenderWidgetHostViewBrowserTest
215 : public RenderWidgetHostViewBrowserTest {
216 public:
217 virtual void SetUp() OVERRIDE {
218 // We expect real pixel output for these tests.
219 UseRealGLContexts();
221 // On legacy windows, these tests need real GL bindings to pass.
222 #if defined(OS_WIN) && !defined(USE_AURA)
223 UseRealGLBindings();
224 #endif
226 RenderWidgetHostViewBrowserTest::SetUp();
229 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
230 // Note: Not appending kForceCompositingMode switch here, since not all bots
231 // support compositing. Some bots will run with compositing on, and others
232 // won't. Therefore, the call to SetUpSourceSurface() later on will detect
233 // whether compositing mode is actually on or not. If not, the tests will
234 // pass blindly, logging a warning message, since we cannot test what the
235 // platform/implementation does not support.
236 RenderWidgetHostViewBrowserTest::SetUpCommandLine(command_line);
239 virtual GURL TestUrl() {
240 return net::FilePathToFileURL(
241 test_dir().AppendASCII("rwhv_compositing_animation.html"));
244 virtual bool SetUpSourceSurface(const char* wait_message) OVERRIDE {
245 if (!IsForceCompositingModeEnabled())
246 return false; // See comment in SetUpCommandLine().
247 #if defined(OS_MACOSX)
248 CHECK(IOSurfaceSupport::Initialize());
249 #endif
251 content::DOMMessageQueue message_queue;
252 NavigateToURL(shell(), TestUrl());
253 if (wait_message != NULL) {
254 std::string result(wait_message);
255 if (!message_queue.WaitForMessage(&result)) {
256 EXPECT_TRUE(false) << "WaitForMessage " << result << " failed.";
257 return false;
261 #if !defined(USE_AURA)
262 if (!GetRenderWidgetHost()->is_accelerated_compositing_active())
263 return false; // Renderer did not turn on accelerated compositing.
264 #endif
266 // Using accelerated compositing, but a compositing surface might not be
267 // available yet. So, wait for it.
268 WaitForCopySourceReady();
269 return true;
273 class NonCompositingRenderWidgetHostViewBrowserTest
274 : public RenderWidgetHostViewBrowserTest {
275 public:
276 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
277 // Note: Appending the kDisableAcceleratedCompositing switch here, but there
278 // are some builds that only use compositing and will ignore this switch.
279 // Therefore, the call to SetUpSourceSurface() later on will detect whether
280 // compositing mode is actually off. If it's on, the tests will pass
281 // blindly, logging a warning message, since we cannot test what the
282 // platform/implementation does not support.
283 command_line->AppendSwitch(switches::kDisableAcceleratedCompositing);
284 RenderWidgetHostViewBrowserTest::SetUpCommandLine(command_line);
287 virtual GURL TestUrl() {
288 return GURL(kAboutBlankURL);
291 virtual bool SetUpSourceSurface(const char* wait_message) OVERRIDE {
292 if (IsForceCompositingModeEnabled())
293 return false; // See comment in SetUpCommandLine().
295 content::DOMMessageQueue message_queue;
296 NavigateToURL(shell(), TestUrl());
297 if (wait_message != NULL) {
298 std::string result(wait_message);
299 if (!message_queue.WaitForMessage(&result)) {
300 EXPECT_TRUE(false) << "WaitForMessage " << result << " failed.";
301 return false;
305 WaitForCopySourceReady();
306 // Return whether the renderer left accelerated compositing turned off.
307 return !GetRenderWidgetHost()->is_accelerated_compositing_active();
311 class FakeFrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
312 public:
313 FakeFrameSubscriber(
314 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback)
315 : callback_(callback) {
318 virtual bool ShouldCaptureFrame(
319 base::Time present_time,
320 scoped_refptr<media::VideoFrame>* storage,
321 DeliverFrameCallback* callback) OVERRIDE {
322 // Only allow one frame capture to be made. Otherwise, the compositor could
323 // start multiple captures, unbounded, and eventually its own limiter logic
324 // will begin invoking |callback| with a |false| result. This flakes out
325 // the unit tests, since they receive a "failed" callback before the later
326 // "success" callbacks.
327 if (callback_.is_null())
328 return false;
329 *storage = media::VideoFrame::CreateBlackFrame(gfx::Size(100, 100));
330 *callback = callback_;
331 callback_.Reset();
332 return true;
335 private:
336 DeliverFrameCallback callback_;
339 // Disable tests for Android and IOS as these platforms have incomplete
340 // implementation.
341 #if !defined(OS_ANDROID) && !defined(OS_IOS)
343 // The CopyFromBackingStore() API should work on all platforms when compositing
344 // is enabled.
345 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest,
346 CopyFromBackingStore) {
347 RunBasicCopyFromBackingStoreTest();
350 // The CopyFromBackingStore() API should work on all platforms when compositing
351 // is disabled.
352 IN_PROC_BROWSER_TEST_F(NonCompositingRenderWidgetHostViewBrowserTest,
353 CopyFromBackingStore) {
354 RunBasicCopyFromBackingStoreTest();
357 // Tests that the callback passed to CopyFromBackingStore is always called,
358 // even when the RenderWidgetHost is deleting in the middle of an async copy.
359 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest,
360 CopyFromBackingStore_CallbackDespiteDelete) {
361 SET_UP_SURFACE_OR_PASS_TEST(NULL);
363 base::RunLoop run_loop;
364 GetRenderViewHost()->CopyFromBackingStore(
365 gfx::Rect(),
366 frame_size(),
367 base::Bind(&RenderWidgetHostViewBrowserTest::FinishCopyFromBackingStore,
368 base::Unretained(this), run_loop.QuitClosure()));
369 // Delete the surface before the callback is run.
370 GetRenderWidgetHostViewPort()->AcceleratedSurfaceRelease();
371 run_loop.Run();
373 EXPECT_EQ(1, callback_invoke_count());
376 // Tests that the callback passed to CopyFromCompositingSurfaceToVideoFrame is
377 // always called, even when the RenderWidgetHost is deleting in the middle of
378 // an async copy.
380 // Test is flaky on Win Aura. http://crbug.com/276783
381 #if (defined(OS_WIN) && defined(USE_AURA)) || \
382 (defined(OS_CHROMEOS) && !defined(NDEBUG))
383 #define MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete \
384 DISABLED_CopyFromCompositingSurface_CallbackDespiteDelete
385 #else
386 #define MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete \
387 CopyFromCompositingSurface_CallbackDespiteDelete
388 #endif
389 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest,
390 MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete) {
391 SET_UP_SURFACE_OR_PASS_TEST(NULL);
392 RenderWidgetHostViewPort* const view = GetRenderWidgetHostViewPort();
393 if (!view->CanCopyToVideoFrame()) {
394 LOG(WARNING) <<
395 ("Blindly passing this test: CopyFromCompositingSurfaceToVideoFrame() "
396 "not supported on this platform.");
397 return;
400 base::RunLoop run_loop;
401 scoped_refptr<media::VideoFrame> dest =
402 media::VideoFrame::CreateBlackFrame(frame_size());
403 view->CopyFromCompositingSurfaceToVideoFrame(
404 gfx::Rect(view->GetViewBounds().size()), dest, base::Bind(
405 &RenderWidgetHostViewBrowserTest::FinishCopyFromCompositingSurface,
406 base::Unretained(this), run_loop.QuitClosure()));
407 // Delete the surface before the callback is run.
408 view->AcceleratedSurfaceRelease();
409 run_loop.Run();
411 EXPECT_EQ(1, callback_invoke_count());
414 // With compositing turned off, no platforms should support the
415 // CopyFromCompositingSurfaceToVideoFrame() API.
416 IN_PROC_BROWSER_TEST_F(NonCompositingRenderWidgetHostViewBrowserTest,
417 CopyFromCompositingSurfaceToVideoFrameCallbackTest) {
418 SET_UP_SURFACE_OR_PASS_TEST(NULL);
419 EXPECT_FALSE(GetRenderWidgetHostViewPort()->CanCopyToVideoFrame());
422 // Test basic frame subscription functionality. We subscribe, and then run
423 // until at least one DeliverFrameCallback has been invoked.
424 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest,
425 FrameSubscriberTest) {
426 SET_UP_SURFACE_OR_PASS_TEST(NULL);
427 RenderWidgetHostViewPort* const view = GetRenderWidgetHostViewPort();
428 if (!view->CanSubscribeFrame()) {
429 LOG(WARNING) << ("Blindly passing this test: Frame subscription not "
430 "supported on this platform.");
431 return;
434 base::RunLoop run_loop;
435 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber(
436 new FakeFrameSubscriber(
437 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered,
438 base::Unretained(this),
439 base::MessageLoopProxy::current(),
440 run_loop.QuitClosure())));
441 view->BeginFrameSubscription(subscriber.Pass());
442 run_loop.Run();
443 view->EndFrameSubscription();
445 EXPECT_LE(1, callback_invoke_count());
446 EXPECT_LE(1, frames_captured());
449 // Test that we can copy twice from an accelerated composited page.
450 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest, CopyTwice) {
451 SET_UP_SURFACE_OR_PASS_TEST(NULL);
452 RenderWidgetHostViewPort* const view = GetRenderWidgetHostViewPort();
453 if (!view->CanCopyToVideoFrame()) {
454 LOG(WARNING) << ("Blindly passing this test: "
455 "CopyFromCompositingSurfaceToVideoFrame() not supported "
456 "on this platform.");
457 return;
460 base::RunLoop run_loop;
461 scoped_refptr<media::VideoFrame> first_output =
462 media::VideoFrame::CreateBlackFrame(frame_size());
463 ASSERT_TRUE(first_output.get());
464 scoped_refptr<media::VideoFrame> second_output =
465 media::VideoFrame::CreateBlackFrame(frame_size());
466 ASSERT_TRUE(second_output.get());
467 view->CopyFromCompositingSurfaceToVideoFrame(
468 gfx::Rect(view->GetViewBounds().size()),
469 first_output,
470 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered,
471 base::Unretained(this),
472 base::MessageLoopProxy::current(),
473 base::Closure(),
474 base::Time::Now()));
475 view->CopyFromCompositingSurfaceToVideoFrame(
476 gfx::Rect(view->GetViewBounds().size()), second_output,
477 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered,
478 base::Unretained(this),
479 base::MessageLoopProxy::current(),
480 run_loop.QuitClosure(),
481 base::Time::Now()));
482 run_loop.Run();
484 EXPECT_EQ(2, callback_invoke_count());
485 EXPECT_EQ(2, frames_captured());
488 class CompositingRenderWidgetHostViewBrowserTestTabCapture
489 : public CompositingRenderWidgetHostViewBrowserTest {
490 public:
491 CompositingRenderWidgetHostViewBrowserTestTabCapture()
492 : expected_copy_from_compositing_surface_result_(false),
493 allowable_error_(0),
494 test_url_("data:text/html,<!doctype html>") {}
496 void CopyFromCompositingSurfaceCallback(base::Closure quit_callback,
497 bool result,
498 const SkBitmap& bitmap) {
499 EXPECT_EQ(expected_copy_from_compositing_surface_result_, result);
500 if (!result) {
501 quit_callback.Run();
502 return;
505 const SkBitmap& expected_bitmap =
506 expected_copy_from_compositing_surface_bitmap_;
507 EXPECT_EQ(expected_bitmap.width(), bitmap.width());
508 EXPECT_EQ(expected_bitmap.height(), bitmap.height());
509 EXPECT_EQ(expected_bitmap.config(), bitmap.config());
510 SkAutoLockPixels expected_bitmap_lock(expected_bitmap);
511 SkAutoLockPixels bitmap_lock(bitmap);
512 int fails = 0;
513 for (int i = 0; i < bitmap.width() && fails < 10; ++i) {
514 for (int j = 0; j < bitmap.height() && fails < 10; ++j) {
515 if (!exclude_rect_.IsEmpty() && exclude_rect_.Contains(i, j))
516 continue;
518 SkColor expected_color = expected_bitmap.getColor(i, j);
519 SkColor color = bitmap.getColor(i, j);
520 int expected_alpha = SkColorGetA(expected_color);
521 int alpha = SkColorGetA(color);
522 int expected_red = SkColorGetR(expected_color);
523 int red = SkColorGetR(color);
524 int expected_green = SkColorGetG(expected_color);
525 int green = SkColorGetG(color);
526 int expected_blue = SkColorGetB(expected_color);
527 int blue = SkColorGetB(color);
528 EXPECT_NEAR(expected_alpha, alpha, allowable_error_)
529 << "expected_color: " << std::hex << expected_color
530 << " color: " << color
531 << " Failed at " << std::dec << i << ", " << j
532 << " Failure " << ++fails;
533 EXPECT_NEAR(expected_red, red, allowable_error_)
534 << "expected_color: " << std::hex << expected_color
535 << " color: " << color
536 << " Failed at " << std::dec << i << ", " << j
537 << " Failure " << ++fails;
538 EXPECT_NEAR(expected_green, green, allowable_error_)
539 << "expected_color: " << std::hex << expected_color
540 << " color: " << color
541 << " Failed at " << std::dec << i << ", " << j
542 << " Failure " << ++fails;
543 EXPECT_NEAR(expected_blue, blue, allowable_error_)
544 << "expected_color: " << std::hex << expected_color
545 << " color: " << color
546 << " Failed at " << std::dec << i << ", " << j
547 << " Failure " << ++fails;
550 EXPECT_LT(fails, 10);
552 quit_callback.Run();
555 void CopyFromCompositingSurfaceCallbackForVideo(
556 scoped_refptr<media::VideoFrame> video_frame,
557 base::Closure quit_callback,
558 bool result) {
559 EXPECT_EQ(expected_copy_from_compositing_surface_result_, result);
560 if (!result) {
561 quit_callback.Run();
562 return;
565 media::SkCanvasVideoRenderer video_renderer;
567 SkBitmap bitmap;
568 bitmap.setConfig(SkBitmap::kARGB_8888_Config,
569 video_frame->visible_rect().width(),
570 video_frame->visible_rect().height(),
571 0, kOpaque_SkAlphaType);
572 bitmap.allocPixels();
574 SkBitmapDevice device(bitmap);
575 SkCanvas canvas(&device);
577 video_renderer.Paint(video_frame.get(),
578 &canvas,
579 video_frame->visible_rect(),
580 0xff);
582 CopyFromCompositingSurfaceCallback(quit_callback,
583 result,
584 bitmap);
587 void SetExpectedCopyFromCompositingSurfaceResult(bool result,
588 const SkBitmap& bitmap) {
589 expected_copy_from_compositing_surface_result_ = result;
590 expected_copy_from_compositing_surface_bitmap_ = bitmap;
593 void SetAllowableError(int amount) { allowable_error_ = amount; }
594 void SetExcludeRect(gfx::Rect exclude) { exclude_rect_ = exclude; }
596 virtual GURL TestUrl() OVERRIDE {
597 return GURL(test_url_);
600 void SetTestUrl(std::string url) { test_url_ = url; }
602 // Loads a page two boxes side-by-side, each half the width of
603 // |html_rect_size|, and with different background colors. The test then
604 // copies from |copy_rect| region of the page into a bitmap of size
605 // |output_size|, and compares that with a bitmap of size
606 // |expected_bitmap_size|.
607 // Note that |output_size| may not have the same size as |copy_rect| (e.g.
608 // when the output is scaled). Also note that |expected_bitmap_size| may not
609 // be the same as |output_size| (e.g. when the device scale factor is not 1).
610 void PerformTestWithLeftRightRects(const gfx::Size& html_rect_size,
611 const gfx::Rect& copy_rect,
612 const gfx::Size& output_size,
613 const gfx::Size& expected_bitmap_size,
614 bool video_frame) {
615 const gfx::Size box_size(html_rect_size.width() / 2,
616 html_rect_size.height());
617 SetTestUrl(base::StringPrintf(
618 "data:text/html,<!doctype html>"
619 "<div class='left'>"
620 " <div class='right'></div>"
621 "</div>"
622 "<style>"
623 "body { padding: 0; margin: 0; }"
624 ".left { position: absolute;"
625 " background: #0ff;"
626 " width: %dpx;"
627 " height: %dpx;"
629 ".right { position: absolute;"
630 " left: %dpx;"
631 " background: #ff0;"
632 " width: %dpx;"
633 " height: %dpx;"
635 "</style>"
636 "<script>"
637 " domAutomationController.setAutomationId(0);"
638 " domAutomationController.send(\"DONE\");"
639 "</script>",
640 box_size.width(),
641 box_size.height(),
642 box_size.width(),
643 box_size.width(),
644 box_size.height()));
646 SET_UP_SURFACE_OR_PASS_TEST("\"DONE\"");
647 if (!ShouldContinueAfterTestURLLoad())
648 return;
650 RenderWidgetHostViewPort* rwhvp = GetRenderWidgetHostViewPort();
652 // The page is loaded in the renderer, wait for a new frame to arrive.
653 uint32 frame = rwhvp->RendererFrameNumber();
654 while (!GetRenderWidgetHost()->ScheduleComposite())
655 GiveItSomeTime();
656 while (rwhvp->RendererFrameNumber() == frame)
657 GiveItSomeTime();
659 SkBitmap expected_bitmap;
660 SetupLeftRightBitmap(expected_bitmap_size, &expected_bitmap);
661 SetExpectedCopyFromCompositingSurfaceResult(true, expected_bitmap);
663 base::RunLoop run_loop;
664 if (video_frame) {
665 // Allow pixel differences as long as we have the right idea.
666 SetAllowableError(0x10);
667 // Exclude the middle two columns which are blended between the two sides.
668 SetExcludeRect(
669 gfx::Rect(output_size.width() / 2 - 1, 0, 2, output_size.height()));
671 scoped_refptr<media::VideoFrame> video_frame =
672 media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
673 expected_bitmap_size,
674 gfx::Rect(expected_bitmap_size),
675 expected_bitmap_size,
676 base::TimeDelta());
678 base::Callback<void(bool success)> callback =
679 base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture::
680 CopyFromCompositingSurfaceCallbackForVideo,
681 base::Unretained(this),
682 video_frame,
683 run_loop.QuitClosure());
684 rwhvp->CopyFromCompositingSurfaceToVideoFrame(copy_rect,
685 video_frame,
686 callback);
687 } else {
688 #if defined(USE_AURA)
689 if (!content::GpuDataManager::GetInstance()
690 ->CanUseGpuBrowserCompositor()) {
691 // Skia rendering can cause color differences, particularly in the
692 // middle two columns.
693 SetAllowableError(2);
694 SetExcludeRect(
695 gfx::Rect(output_size.width() / 2 - 1, 0, 2, output_size.height()));
697 #endif
699 base::Callback<void(bool, const SkBitmap&)> callback =
700 base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture::
701 CopyFromCompositingSurfaceCallback,
702 base::Unretained(this),
703 run_loop.QuitClosure());
704 rwhvp->CopyFromCompositingSurface(copy_rect, output_size, callback);
706 run_loop.Run();
709 // Sets up |bitmap| to have size |copy_size|. It floods the left half with
710 // #0ff and the right half with #ff0.
711 void SetupLeftRightBitmap(const gfx::Size& copy_size, SkBitmap* bitmap) {
712 bitmap->setConfig(
713 SkBitmap::kARGB_8888_Config, copy_size.width(), copy_size.height());
714 bitmap->allocPixels();
715 // Left half is #0ff.
716 bitmap->eraseARGB(255, 0, 255, 255);
717 // Right half is #ff0.
719 SkAutoLockPixels lock(*bitmap);
720 for (int i = 0; i < copy_size.width() / 2; ++i) {
721 for (int j = 0; j < copy_size.height(); ++j) {
722 *(bitmap->getAddr32(copy_size.width() / 2 + i, j)) =
723 SkColorSetARGB(255, 255, 255, 0);
729 protected:
730 virtual bool ShouldContinueAfterTestURLLoad() {
731 return true;
734 private:
735 bool expected_copy_from_compositing_surface_result_;
736 SkBitmap expected_copy_from_compositing_surface_bitmap_;
737 int allowable_error_;
738 gfx::Rect exclude_rect_;
739 std::string test_url_;
742 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTestTabCapture,
743 CopyFromCompositingSurface_Origin_Unscaled) {
744 gfx::Rect copy_rect(400, 300);
745 gfx::Size output_size = copy_rect.size();
746 gfx::Size expected_bitmap_size = output_size;
747 gfx::Size html_rect_size(400, 300);
748 bool video_frame = false;
749 PerformTestWithLeftRightRects(html_rect_size,
750 copy_rect,
751 output_size,
752 expected_bitmap_size,
753 video_frame);
756 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTestTabCapture,
757 CopyFromCompositingSurface_Origin_Scaled) {
758 gfx::Rect copy_rect(400, 300);
759 gfx::Size output_size(200, 100);
760 gfx::Size expected_bitmap_size = output_size;
761 gfx::Size html_rect_size(400, 300);
762 bool video_frame = false;
763 PerformTestWithLeftRightRects(html_rect_size,
764 copy_rect,
765 output_size,
766 expected_bitmap_size,
767 video_frame);
770 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTestTabCapture,
771 CopyFromCompositingSurface_Cropped_Unscaled) {
772 // Grab 60x60 pixels from the center of the tab contents.
773 gfx::Rect copy_rect(400, 300);
774 copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(30, 30),
775 gfx::Size(60, 60));
776 gfx::Size output_size = copy_rect.size();
777 gfx::Size expected_bitmap_size = output_size;
778 gfx::Size html_rect_size(400, 300);
779 bool video_frame = false;
780 PerformTestWithLeftRightRects(html_rect_size,
781 copy_rect,
782 output_size,
783 expected_bitmap_size,
784 video_frame);
787 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTestTabCapture,
788 CopyFromCompositingSurface_Cropped_Scaled) {
789 // Grab 60x60 pixels from the center of the tab contents.
790 gfx::Rect copy_rect(400, 300);
791 copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(30, 30),
792 gfx::Size(60, 60));
793 gfx::Size output_size(20, 10);
794 gfx::Size expected_bitmap_size = output_size;
795 gfx::Size html_rect_size(400, 300);
796 bool video_frame = false;
797 PerformTestWithLeftRightRects(html_rect_size,
798 copy_rect,
799 output_size,
800 expected_bitmap_size,
801 video_frame);
804 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTestTabCapture,
805 CopyFromCompositingSurface_ForVideoFrame) {
806 // Grab 90x60 pixels from the center of the tab contents.
807 gfx::Rect copy_rect(400, 300);
808 copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(45, 30),
809 gfx::Size(90, 60));
810 gfx::Size output_size = copy_rect.size();
811 gfx::Size expected_bitmap_size = output_size;
812 gfx::Size html_rect_size(400, 300);
813 bool video_frame = true;
814 PerformTestWithLeftRightRects(html_rect_size,
815 copy_rect,
816 output_size,
817 expected_bitmap_size,
818 video_frame);
821 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTestTabCapture,
822 CopyFromCompositingSurface_ForVideoFrame_Scaled) {
823 // Grab 90x60 pixels from the center of the tab contents.
824 gfx::Rect copy_rect(400, 300);
825 copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(45, 30),
826 gfx::Size(90, 60));
827 // Scale to 30 x 20 (preserve aspect ratio).
828 gfx::Size output_size(30, 20);
829 gfx::Size expected_bitmap_size = output_size;
830 gfx::Size html_rect_size(400, 300);
831 bool video_frame = true;
832 PerformTestWithLeftRightRects(html_rect_size,
833 copy_rect,
834 output_size,
835 expected_bitmap_size,
836 video_frame);
839 class CompositingRenderWidgetHostViewTabCaptureHighDPI
840 : public CompositingRenderWidgetHostViewBrowserTestTabCapture {
841 public:
842 CompositingRenderWidgetHostViewTabCaptureHighDPI()
843 : kScale(2.f) {
846 virtual void SetUpCommandLine(CommandLine* cmd) OVERRIDE {
847 CompositingRenderWidgetHostViewBrowserTestTabCapture::SetUpCommandLine(cmd);
848 cmd->AppendSwitchASCII(switches::kForceDeviceScaleFactor,
849 base::StringPrintf("%f", scale()));
850 #if defined(OS_WIN)
851 cmd->AppendSwitchASCII(switches::kHighDPISupport, "1");
852 gfx::EnableHighDPISupport();
853 #endif
856 float scale() const { return kScale; }
858 private:
859 virtual bool ShouldContinueAfterTestURLLoad() OVERRIDE {
860 PASS_TEST_IF_SCALE_FACTOR_NOT_SUPPORTED(scale());
861 return true;
864 const float kScale;
866 DISALLOW_COPY_AND_ASSIGN(CompositingRenderWidgetHostViewTabCaptureHighDPI);
869 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewTabCaptureHighDPI,
870 CopyFromCompositingSurface) {
871 gfx::Rect copy_rect(200, 150);
872 gfx::Size output_size = copy_rect.size();
873 gfx::Size expected_bitmap_size =
874 gfx::ToFlooredSize(gfx::ScaleSize(output_size, scale(), scale()));
875 gfx::Size html_rect_size(200, 150);
876 bool video_frame = false;
877 PerformTestWithLeftRightRects(html_rect_size,
878 copy_rect,
879 output_size,
880 expected_bitmap_size,
881 video_frame);
884 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewTabCaptureHighDPI,
885 CopyFromCompositingSurfaceVideoFrame) {
886 gfx::Size html_rect_size(200, 150);
887 // Grab 90x60 pixels from the center of the tab contents.
888 gfx::Rect copy_rect =
889 gfx::Rect(gfx::Rect(html_rect_size).CenterPoint() - gfx::Vector2d(45, 30),
890 gfx::Size(90, 60));
891 gfx::Size output_size = copy_rect.size();
892 gfx::Size expected_bitmap_size =
893 gfx::ToFlooredSize(gfx::ScaleSize(output_size, scale(), scale()));
894 bool video_frame = true;
895 PerformTestWithLeftRightRects(html_rect_size,
896 copy_rect,
897 output_size,
898 expected_bitmap_size,
899 video_frame);
902 #endif // !defined(OS_ANDROID) && !defined(OS_IOS)
904 } // namespace
905 } // namespace content