Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / render_widget_host_view_browsertest.cc
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.
4
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/browser/renderer_host/render_widget_host_view_base.h"
14 #include "content/public/browser/gpu_data_manager.h"
15 #include "content/public/browser/render_view_host.h"
16 #include "content/public/browser/render_widget_host_view_frame_subscriber.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/public/test/content_browser_test.h"
23 #include "content/public/test/content_browser_test_utils.h"
24 #include "content/shell/browser/shell.h"
25 #include "media/base/video_frame.h"
26 #include "media/filters/skcanvas_video_renderer.h"
27 #include "net/base/filename_util.h"
28 #include "third_party/skia/include/core/SkBitmap.h"
29 #include "third_party/skia/include/core/SkCanvas.h"
30 #include "ui/base/layout.h"
31 #include "ui/base/ui_base_switches.h"
32 #include "ui/gfx/geometry/size_conversions.h"
33 #include "ui/gfx/switches.h"
34 #include "ui/gl/gl_switches.h"
35
36 #if defined(OS_WIN)
37 #include "base/win/windows_version.h"
38 #include "ui/gfx/win/dpi.h"
39 #endif
40
41 namespace content {
42 namespace {
43
44 // Convenience macro: Short-circuit a pass for the tests where platform support
45 // for forced-compositing mode (or disabled-compositing mode) is lacking.
46 #define SET_UP_SURFACE_OR_PASS_TEST(wait_message)  \
47   if (!SetUpSourceSurface(wait_message)) {  \
48     LOG(WARNING)  \
49         << ("Blindly passing this test: This platform does not support "  \
50             "forced compositing (or forced-disabled compositing) mode.");  \
51     return;  \
52   }
53
54 // Common base class for browser tests.  This is subclassed twice: Once to test
55 // the browser in forced-compositing mode, and once to test with compositing
56 // mode disabled.
57 class RenderWidgetHostViewBrowserTest : public ContentBrowserTest {
58  public:
59   RenderWidgetHostViewBrowserTest()
60       : frame_size_(400, 300),
61         callback_invoke_count_(0),
62         frames_captured_(0) {}
63
64   void SetUpOnMainThread() override {
65     ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &test_dir_));
66   }
67
68   // Attempts to set up the source surface.  Returns false if unsupported on the
69   // current platform.
70   virtual bool SetUpSourceSurface(const char* wait_message) = 0;
71
72   int callback_invoke_count() const {
73     return callback_invoke_count_;
74   }
75
76   int frames_captured() const {
77     return frames_captured_;
78   }
79
80   const gfx::Size& frame_size() const {
81     return frame_size_;
82   }
83
84   const base::FilePath& test_dir() const {
85     return test_dir_;
86   }
87
88   RenderViewHost* GetRenderViewHost() const {
89     RenderViewHost* const rvh = shell()->web_contents()->GetRenderViewHost();
90     CHECK(rvh);
91     return rvh;
92   }
93
94   RenderWidgetHostImpl* GetRenderWidgetHost() const {
95     RenderWidgetHostImpl* const rwh = RenderWidgetHostImpl::From(
96         shell()->web_contents()->GetRenderWidgetHostView()->
97             GetRenderWidgetHost());
98     CHECK(rwh);
99     return rwh;
100   }
101
102   RenderWidgetHostViewBase* GetRenderWidgetHostView() const {
103     return static_cast<RenderWidgetHostViewBase*>(
104         GetRenderViewHost()->GetView());
105   }
106
107   // Callback when using CopyFromBackingStore() API.
108   void FinishCopyFromBackingStore(const base::Closure& quit_closure,
109                                   bool frame_captured,
110                                   const SkBitmap& bitmap) {
111     ++callback_invoke_count_;
112     if (frame_captured) {
113       ++frames_captured_;
114       EXPECT_FALSE(bitmap.empty());
115     }
116     if (!quit_closure.is_null())
117       quit_closure.Run();
118   }
119
120   // Callback when using CopyFromCompositingSurfaceToVideoFrame() API.
121   void FinishCopyFromCompositingSurface(const base::Closure& quit_closure,
122                                         bool frame_captured) {
123     ++callback_invoke_count_;
124     if (frame_captured)
125       ++frames_captured_;
126     if (!quit_closure.is_null())
127       quit_closure.Run();
128   }
129
130   // Callback when using frame subscriber API.
131   void FrameDelivered(const scoped_refptr<base::MessageLoopProxy>& loop,
132                       base::Closure quit_closure,
133                       base::TimeTicks timestamp,
134                       bool frame_captured) {
135     ++callback_invoke_count_;
136     if (frame_captured)
137       ++frames_captured_;
138     if (!quit_closure.is_null())
139       loop->PostTask(FROM_HERE, quit_closure);
140   }
141
142   // Copy one frame using the CopyFromBackingStore API.
143   void RunBasicCopyFromBackingStoreTest() {
144     SET_UP_SURFACE_OR_PASS_TEST(NULL);
145
146     // Repeatedly call CopyFromBackingStore() since, on some platforms (e.g.,
147     // Windows), the operation will fail until the first "present" has been
148     // made.
149     int count_attempts = 0;
150     while (true) {
151       ++count_attempts;
152       base::RunLoop run_loop;
153       GetRenderViewHost()->CopyFromBackingStore(
154           gfx::Rect(),
155           frame_size(),
156           base::Bind(
157               &RenderWidgetHostViewBrowserTest::FinishCopyFromBackingStore,
158               base::Unretained(this),
159               run_loop.QuitClosure()),
160           kN32_SkColorType);
161       run_loop.Run();
162
163       if (frames_captured())
164         break;
165       else
166         GiveItSomeTime();
167     }
168
169     EXPECT_EQ(count_attempts, callback_invoke_count());
170     EXPECT_EQ(1, frames_captured());
171   }
172
173  protected:
174   // Waits until the source is available for copying.
175   void WaitForCopySourceReady() {
176     while (!GetRenderWidgetHostView()->IsSurfaceAvailableForCopy())
177       GiveItSomeTime();
178   }
179
180   // Run the current message loop for a short time without unwinding the current
181   // call stack.
182   static void GiveItSomeTime() {
183     base::RunLoop run_loop;
184     base::MessageLoop::current()->PostDelayedTask(
185         FROM_HERE,
186         run_loop.QuitClosure(),
187         base::TimeDelta::FromMilliseconds(10));
188     run_loop.Run();
189   }
190
191  private:
192   const gfx::Size frame_size_;
193   base::FilePath test_dir_;
194   int callback_invoke_count_;
195   int frames_captured_;
196 };
197
198 enum CompositingMode {
199   GL_COMPOSITING,
200   SOFTWARE_COMPOSITING,
201 };
202
203 class CompositingRenderWidgetHostViewBrowserTest
204     : public RenderWidgetHostViewBrowserTest,
205       public testing::WithParamInterface<CompositingMode> {
206  public:
207   explicit CompositingRenderWidgetHostViewBrowserTest()
208       : compositing_mode_(GetParam()) {}
209
210   void SetUp() override {
211     if (compositing_mode_ == SOFTWARE_COMPOSITING)
212       UseSoftwareCompositing();
213     RenderWidgetHostViewBrowserTest::SetUp();
214   }
215
216   virtual GURL TestUrl() {
217     return net::FilePathToFileURL(
218         test_dir().AppendASCII("rwhv_compositing_animation.html"));
219   }
220
221   bool SetUpSourceSurface(const char* wait_message) override {
222     content::DOMMessageQueue message_queue;
223     NavigateToURL(shell(), TestUrl());
224     if (wait_message != NULL) {
225       std::string result(wait_message);
226       if (!message_queue.WaitForMessage(&result)) {
227         EXPECT_TRUE(false) << "WaitForMessage " << result << " failed.";
228         return false;
229       }
230     }
231
232     // A frame might not be available yet. So, wait for it.
233     WaitForCopySourceReady();
234     return true;
235   }
236
237  private:
238   const CompositingMode compositing_mode_;
239
240   DISALLOW_COPY_AND_ASSIGN(CompositingRenderWidgetHostViewBrowserTest);
241 };
242
243 class FakeFrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
244  public:
245   FakeFrameSubscriber(
246     RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback)
247       : callback_(callback) {
248   }
249
250   bool ShouldCaptureFrame(const gfx::Rect& damage_rect,
251                           base::TimeTicks present_time,
252                           scoped_refptr<media::VideoFrame>* storage,
253                           DeliverFrameCallback* callback) override {
254     // Only allow one frame capture to be made.  Otherwise, the compositor could
255     // start multiple captures, unbounded, and eventually its own limiter logic
256     // will begin invoking |callback| with a |false| result.  This flakes out
257     // the unit tests, since they receive a "failed" callback before the later
258     // "success" callbacks.
259     if (callback_.is_null())
260       return false;
261     *storage = media::VideoFrame::CreateBlackFrame(gfx::Size(100, 100));
262     *callback = callback_;
263     callback_.Reset();
264     return true;
265   }
266
267  private:
268   DeliverFrameCallback callback_;
269 };
270
271 // Disable tests for Android and IOS as these platforms have incomplete
272 // implementation.
273 #if !defined(OS_ANDROID) && !defined(OS_IOS)
274
275 // The CopyFromBackingStore() API should work on all platforms when compositing
276 // is enabled.
277 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest,
278                        CopyFromBackingStore) {
279   RunBasicCopyFromBackingStoreTest();
280 }
281
282 // Tests that the callback passed to CopyFromBackingStore is always called,
283 // even when the RenderWidgetHost is deleting in the middle of an async copy.
284 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest,
285                        CopyFromBackingStore_CallbackDespiteDelete) {
286   SET_UP_SURFACE_OR_PASS_TEST(NULL);
287
288   base::RunLoop run_loop;
289   GetRenderViewHost()->CopyFromBackingStore(
290       gfx::Rect(),
291       frame_size(),
292       base::Bind(&RenderWidgetHostViewBrowserTest::FinishCopyFromBackingStore,
293                  base::Unretained(this),
294                  run_loop.QuitClosure()),
295       kN32_SkColorType);
296   run_loop.Run();
297
298   EXPECT_EQ(1, callback_invoke_count());
299 }
300
301 // Tests that the callback passed to CopyFromCompositingSurfaceToVideoFrame is
302 // always called, even when the RenderWidgetHost is deleting in the middle of
303 // an async copy.
304 //
305 // Test is flaky on Win. http://crbug.com/276783
306 #if defined(OS_WIN) || (defined(OS_CHROMEOS) && !defined(NDEBUG))
307 #define MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete \
308   DISABLED_CopyFromCompositingSurface_CallbackDespiteDelete
309 #else
310 #define MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete \
311   CopyFromCompositingSurface_CallbackDespiteDelete
312 #endif
313 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest,
314                        MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete) {
315   SET_UP_SURFACE_OR_PASS_TEST(NULL);
316   RenderWidgetHostViewBase* const view = GetRenderWidgetHostView();
317   if (!view->CanCopyToVideoFrame()) {
318     LOG(WARNING) <<
319         ("Blindly passing this test: CopyFromCompositingSurfaceToVideoFrame() "
320          "not supported on this platform.");
321     return;
322   }
323
324   base::RunLoop run_loop;
325   scoped_refptr<media::VideoFrame> dest =
326       media::VideoFrame::CreateBlackFrame(frame_size());
327   view->CopyFromCompositingSurfaceToVideoFrame(
328       gfx::Rect(view->GetViewBounds().size()), dest, base::Bind(
329           &RenderWidgetHostViewBrowserTest::FinishCopyFromCompositingSurface,
330           base::Unretained(this), run_loop.QuitClosure()));
331   run_loop.Run();
332
333   EXPECT_EQ(1, callback_invoke_count());
334 }
335
336 // Test basic frame subscription functionality.  We subscribe, and then run
337 // until at least one DeliverFrameCallback has been invoked.
338 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest,
339                        FrameSubscriberTest) {
340   SET_UP_SURFACE_OR_PASS_TEST(NULL);
341   RenderWidgetHostViewBase* const view = GetRenderWidgetHostView();
342   if (!view->CanSubscribeFrame()) {
343     LOG(WARNING) << ("Blindly passing this test: Frame subscription not "
344                      "supported on this platform.");
345     return;
346   }
347
348   base::RunLoop run_loop;
349   scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber(
350       new FakeFrameSubscriber(
351           base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered,
352                      base::Unretained(this),
353                      base::MessageLoopProxy::current(),
354                      run_loop.QuitClosure())));
355   view->BeginFrameSubscription(subscriber.Pass());
356   run_loop.Run();
357   view->EndFrameSubscription();
358
359   EXPECT_LE(1, callback_invoke_count());
360   EXPECT_LE(1, frames_captured());
361 }
362
363 // Test that we can copy twice from an accelerated composited page.
364 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest, CopyTwice) {
365   SET_UP_SURFACE_OR_PASS_TEST(NULL);
366   RenderWidgetHostViewBase* const view = GetRenderWidgetHostView();
367   if (!view->CanCopyToVideoFrame()) {
368     LOG(WARNING) << ("Blindly passing this test: "
369                      "CopyFromCompositingSurfaceToVideoFrame() not supported "
370                      "on this platform.");
371     return;
372   }
373
374   base::RunLoop run_loop;
375   scoped_refptr<media::VideoFrame> first_output =
376       media::VideoFrame::CreateBlackFrame(frame_size());
377   ASSERT_TRUE(first_output.get());
378   scoped_refptr<media::VideoFrame> second_output =
379       media::VideoFrame::CreateBlackFrame(frame_size());
380   ASSERT_TRUE(second_output.get());
381   view->CopyFromCompositingSurfaceToVideoFrame(
382       gfx::Rect(view->GetViewBounds().size()),
383       first_output,
384       base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered,
385                  base::Unretained(this),
386                  base::MessageLoopProxy::current(),
387                  base::Closure(),
388                  base::TimeTicks::Now()));
389   view->CopyFromCompositingSurfaceToVideoFrame(
390       gfx::Rect(view->GetViewBounds().size()),
391       second_output,
392       base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered,
393                  base::Unretained(this),
394                  base::MessageLoopProxy::current(),
395                  run_loop.QuitClosure(),
396                  base::TimeTicks::Now()));
397   run_loop.Run();
398
399   EXPECT_EQ(2, callback_invoke_count());
400   EXPECT_EQ(2, frames_captured());
401 }
402
403 class CompositingRenderWidgetHostViewBrowserTestTabCapture
404     : public CompositingRenderWidgetHostViewBrowserTest {
405  public:
406   CompositingRenderWidgetHostViewBrowserTestTabCapture()
407       : expected_copy_from_compositing_surface_result_(false),
408         allowable_error_(0),
409         test_url_("data:text/html,<!doctype html>") {}
410
411   void SetUp() override {
412     EnablePixelOutput();
413     CompositingRenderWidgetHostViewBrowserTest::SetUp();
414   }
415
416   void CopyFromCompositingSurfaceCallback(base::Closure quit_callback,
417                                           bool result,
418                                           const SkBitmap& bitmap) {
419     EXPECT_EQ(expected_copy_from_compositing_surface_result_, result);
420     if (!result) {
421       quit_callback.Run();
422       return;
423     }
424
425     const SkBitmap& expected_bitmap =
426         expected_copy_from_compositing_surface_bitmap_;
427     EXPECT_EQ(expected_bitmap.width(), bitmap.width());
428     EXPECT_EQ(expected_bitmap.height(), bitmap.height());
429     EXPECT_EQ(expected_bitmap.colorType(), bitmap.colorType());
430     SkAutoLockPixels expected_bitmap_lock(expected_bitmap);
431     SkAutoLockPixels bitmap_lock(bitmap);
432     int fails = 0;
433     for (int i = 0; i < bitmap.width() && fails < 10; ++i) {
434       for (int j = 0; j < bitmap.height() && fails < 10; ++j) {
435         if (!exclude_rect_.IsEmpty() && exclude_rect_.Contains(i, j))
436           continue;
437
438         SkColor expected_color = expected_bitmap.getColor(i, j);
439         SkColor color = bitmap.getColor(i, j);
440         int expected_alpha = SkColorGetA(expected_color);
441         int alpha = SkColorGetA(color);
442         int expected_red = SkColorGetR(expected_color);
443         int red = SkColorGetR(color);
444         int expected_green = SkColorGetG(expected_color);
445         int green = SkColorGetG(color);
446         int expected_blue = SkColorGetB(expected_color);
447         int blue = SkColorGetB(color);
448         EXPECT_NEAR(expected_alpha, alpha, allowable_error_)
449             << "expected_color: " << std::hex << expected_color
450             << " color: " <<  color
451             << " Failed at " << std::dec << i << ", " << j
452             << " Failure " << ++fails;
453         EXPECT_NEAR(expected_red, red, allowable_error_)
454             << "expected_color: " << std::hex << expected_color
455             << " color: " <<  color
456             << " Failed at " << std::dec << i << ", " << j
457             << " Failure " << ++fails;
458         EXPECT_NEAR(expected_green, green, allowable_error_)
459             << "expected_color: " << std::hex << expected_color
460             << " color: " <<  color
461             << " Failed at " << std::dec << i << ", " << j
462             << " Failure " << ++fails;
463         EXPECT_NEAR(expected_blue, blue, allowable_error_)
464             << "expected_color: " << std::hex << expected_color
465             << " color: " <<  color
466             << " Failed at " << std::dec << i << ", " << j
467             << " Failure " << ++fails;
468       }
469     }
470     EXPECT_LT(fails, 10);
471
472     quit_callback.Run();
473   }
474
475   void CopyFromCompositingSurfaceCallbackForVideo(
476       scoped_refptr<media::VideoFrame> video_frame,
477       base::Closure quit_callback,
478       bool result) {
479     EXPECT_EQ(expected_copy_from_compositing_surface_result_, result);
480     if (!result) {
481       quit_callback.Run();
482       return;
483     }
484
485     media::SkCanvasVideoRenderer video_renderer;
486
487     SkBitmap bitmap;
488     bitmap.allocN32Pixels(video_frame->visible_rect().width(),
489                           video_frame->visible_rect().height());
490     // Don't clear the canvas because drawing a video frame by Src mode.
491     SkCanvas canvas(bitmap);
492     video_renderer.Copy(video_frame, &canvas);
493
494     CopyFromCompositingSurfaceCallback(quit_callback,
495                                        result,
496                                        bitmap);
497   }
498
499   void SetExpectedCopyFromCompositingSurfaceResult(bool result,
500                                                    const SkBitmap& bitmap) {
501     expected_copy_from_compositing_surface_result_ = result;
502     expected_copy_from_compositing_surface_bitmap_ = bitmap;
503   }
504
505   void SetAllowableError(int amount) { allowable_error_ = amount; }
506   void SetExcludeRect(gfx::Rect exclude) { exclude_rect_ = exclude; }
507
508   GURL TestUrl() override { return GURL(test_url_); }
509
510   void SetTestUrl(std::string url) { test_url_ = url; }
511
512   // Loads a page two boxes side-by-side, each half the width of
513   // |html_rect_size|, and with different background colors. The test then
514   // copies from |copy_rect| region of the page into a bitmap of size
515   // |output_size|, and examines the resulting bitmap/VideoFrame.
516   // Note that |output_size| may not have the same size as |copy_rect| (e.g.
517   // when the output is scaled).
518   void PerformTestWithLeftRightRects(const gfx::Size& html_rect_size,
519                                      const gfx::Rect& copy_rect,
520                                      const gfx::Size& output_size,
521                                      bool video_frame) {
522     const gfx::Size box_size(html_rect_size.width() / 2,
523                              html_rect_size.height());
524     SetTestUrl(base::StringPrintf(
525         "data:text/html,<!doctype html>"
526         "<div class='left'>"
527         "  <div class='right'></div>"
528         "</div>"
529         "<style>"
530         "body { padding: 0; margin: 0; }"
531         ".left { position: absolute;"
532         "        background: #0ff;"
533         "        width: %dpx;"
534         "        height: %dpx;"
535         "}"
536         ".right { position: absolute;"
537         "         left: %dpx;"
538         "         background: #ff0;"
539         "         width: %dpx;"
540         "         height: %dpx;"
541         "}"
542         "</style>"
543         "<script>"
544         "  domAutomationController.setAutomationId(0);"
545         "  domAutomationController.send(\"DONE\");"
546         "</script>",
547         box_size.width(),
548         box_size.height(),
549         box_size.width(),
550         box_size.width(),
551         box_size.height()));
552
553     SET_UP_SURFACE_OR_PASS_TEST("\"DONE\"");
554     if (!ShouldContinueAfterTestURLLoad())
555       return;
556
557     RenderWidgetHostViewBase* rwhvp = GetRenderWidgetHostView();
558     if (video_frame && !rwhvp->CanCopyToVideoFrame()) {
559       // This should only happen on Mac when using the software compositor.
560       // Otherwise, raise an error. This can be removed when Mac is moved to a
561       // browser compositor.
562       // http://crbug.com/314190
563 #if defined(OS_MACOSX)
564       if (!content::GpuDataManager::GetInstance()->GpuAccessAllowed(NULL)) {
565         LOG(WARNING) << ("Blindly passing this test because copying to "
566                          "video frames is not supported on this platform.");
567         return;
568       }
569 #endif
570       NOTREACHED();
571     }
572
573     // The page is loaded in the renderer, wait for a new frame to arrive.
574     uint32 frame = rwhvp->RendererFrameNumber();
575     while (!GetRenderWidgetHost()->ScheduleComposite())
576       GiveItSomeTime();
577     while (rwhvp->RendererFrameNumber() == frame)
578       GiveItSomeTime();
579
580     SkBitmap expected_bitmap;
581     SetupLeftRightBitmap(output_size, &expected_bitmap);
582     SetExpectedCopyFromCompositingSurfaceResult(true, expected_bitmap);
583
584     base::RunLoop run_loop;
585     if (video_frame) {
586       // Allow pixel differences as long as we have the right idea.
587       SetAllowableError(0x10);
588       // Exclude the middle two columns which are blended between the two sides.
589       SetExcludeRect(
590           gfx::Rect(output_size.width() / 2 - 1, 0, 2, output_size.height()));
591
592       scoped_refptr<media::VideoFrame> video_frame =
593           media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
594                                          output_size,
595                                          gfx::Rect(output_size),
596                                          output_size,
597                                          base::TimeDelta());
598
599       base::Callback<void(bool success)> callback =
600           base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture::
601                          CopyFromCompositingSurfaceCallbackForVideo,
602                      base::Unretained(this),
603                      video_frame,
604                      run_loop.QuitClosure());
605       rwhvp->CopyFromCompositingSurfaceToVideoFrame(copy_rect,
606                                                     video_frame,
607                                                     callback);
608     } else {
609       if (IsDelegatedRendererEnabled()) {
610         if (!content::GpuDataManager::GetInstance()
611                  ->CanUseGpuBrowserCompositor()) {
612           // Skia rendering can cause color differences, particularly in the
613           // middle two columns.
614           SetAllowableError(2);
615           SetExcludeRect(gfx::Rect(
616               output_size.width() / 2 - 1, 0, 2, output_size.height()));
617         }
618       }
619
620       base::Callback<void(bool, const SkBitmap&)> callback =
621           base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture::
622                        CopyFromCompositingSurfaceCallback,
623                    base::Unretained(this),
624                    run_loop.QuitClosure());
625       rwhvp->CopyFromCompositingSurface(copy_rect,
626                                         output_size,
627                                         callback,
628                                         kN32_SkColorType);
629     }
630     run_loop.Run();
631   }
632
633   // Sets up |bitmap| to have size |copy_size|. It floods the left half with
634   // #0ff and the right half with #ff0.
635   void SetupLeftRightBitmap(const gfx::Size& copy_size, SkBitmap* bitmap) {
636     bitmap->allocN32Pixels(copy_size.width(), copy_size.height());
637     // Left half is #0ff.
638     bitmap->eraseARGB(255, 0, 255, 255);
639     // Right half is #ff0.
640     {
641       SkAutoLockPixels lock(*bitmap);
642       for (int i = 0; i < copy_size.width() / 2; ++i) {
643         for (int j = 0; j < copy_size.height(); ++j) {
644           *(bitmap->getAddr32(copy_size.width() / 2 + i, j)) =
645               SkColorSetARGB(255, 255, 255, 0);
646         }
647       }
648     }
649   }
650
651  protected:
652   virtual bool ShouldContinueAfterTestURLLoad() {
653     return true;
654   }
655
656  private:
657   bool expected_copy_from_compositing_surface_result_;
658   SkBitmap expected_copy_from_compositing_surface_bitmap_;
659   int allowable_error_;
660   gfx::Rect exclude_rect_;
661   std::string test_url_;
662 };
663
664 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
665                        CopyFromCompositingSurface_Origin_Unscaled) {
666   gfx::Rect copy_rect(400, 300);
667   gfx::Size output_size = copy_rect.size();
668   gfx::Size html_rect_size(400, 300);
669   bool video_frame = false;
670   PerformTestWithLeftRightRects(html_rect_size,
671                                 copy_rect,
672                                 output_size,
673                                 video_frame);
674 }
675
676 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
677                        CopyFromCompositingSurface_Origin_Scaled) {
678   gfx::Rect copy_rect(400, 300);
679   gfx::Size output_size(200, 100);
680   gfx::Size html_rect_size(400, 300);
681   bool video_frame = false;
682   PerformTestWithLeftRightRects(html_rect_size,
683                                 copy_rect,
684                                 output_size,
685                                 video_frame);
686 }
687
688 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
689                        CopyFromCompositingSurface_Cropped_Unscaled) {
690   // Grab 60x60 pixels from the center of the tab contents.
691   gfx::Rect copy_rect(400, 300);
692   copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(30, 30),
693                         gfx::Size(60, 60));
694   gfx::Size output_size = copy_rect.size();
695   gfx::Size html_rect_size(400, 300);
696   bool video_frame = false;
697   PerformTestWithLeftRightRects(html_rect_size,
698                                 copy_rect,
699                                 output_size,
700                                 video_frame);
701 }
702
703 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
704                        CopyFromCompositingSurface_Cropped_Scaled) {
705   // Grab 60x60 pixels from the center of the tab contents.
706   gfx::Rect copy_rect(400, 300);
707   copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(30, 30),
708                         gfx::Size(60, 60));
709   gfx::Size output_size(20, 10);
710   gfx::Size html_rect_size(400, 300);
711   bool video_frame = false;
712   PerformTestWithLeftRightRects(html_rect_size,
713                                 copy_rect,
714                                 output_size,
715                                 video_frame);
716 }
717
718 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
719                        CopyFromCompositingSurface_ForVideoFrame) {
720   // Grab 90x60 pixels from the center of the tab contents.
721   gfx::Rect copy_rect(400, 300);
722   copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(45, 30),
723                         gfx::Size(90, 60));
724   gfx::Size output_size = copy_rect.size();
725   gfx::Size html_rect_size(400, 300);
726   bool video_frame = true;
727   PerformTestWithLeftRightRects(html_rect_size,
728                                 copy_rect,
729                                 output_size,
730                                 video_frame);
731 }
732
733 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
734                        CopyFromCompositingSurface_ForVideoFrame_Scaled) {
735   // Grab 90x60 pixels from the center of the tab contents.
736   gfx::Rect copy_rect(400, 300);
737   copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(45, 30),
738                         gfx::Size(90, 60));
739   // Scale to 30 x 20 (preserve aspect ratio).
740   gfx::Size output_size(30, 20);
741   gfx::Size html_rect_size(400, 300);
742   bool video_frame = true;
743   PerformTestWithLeftRightRects(html_rect_size,
744                                 copy_rect,
745                                 output_size,
746                                 video_frame);
747 }
748
749 class CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI
750     : public CompositingRenderWidgetHostViewBrowserTestTabCapture {
751  public:
752   CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI() {}
753
754  protected:
755   void SetUpCommandLine(base::CommandLine* cmd) override {
756     CompositingRenderWidgetHostViewBrowserTestTabCapture::SetUpCommandLine(cmd);
757     cmd->AppendSwitchASCII(switches::kForceDeviceScaleFactor,
758                            base::StringPrintf("%f", scale()));
759   }
760
761   bool ShouldContinueAfterTestURLLoad() override {
762     // Short-circuit a pass for platforms where setting up high-DPI fails.
763     const float actual_scale_factor =
764         GetScaleFactorForView(GetRenderWidgetHostView());
765     if (actual_scale_factor != scale()) {
766       LOG(WARNING) << "Blindly passing this test; unable to force device scale "
767                    << "factor: seems to be " << actual_scale_factor
768                    << " but expected " << scale();
769       return false;
770     }
771     VLOG(1) << ("Successfully forced device scale factor.  Moving forward with "
772                 "this test!  :-)");
773     return true;
774   }
775
776   static float scale() { return 2.0f; }
777
778  private:
779   DISALLOW_COPY_AND_ASSIGN(
780       CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI);
781 };
782
783 // ImageSkia (related to ResourceBundle) implementation crashes the process on
784 // Windows when this content_browsertest forces a device scale factor.
785 // http://crbug.com/399349
786 //
787 // These tests are flaky on ChromeOS builders.  See http://crbug.com/406018.
788 #if defined(OS_WIN) || defined(OS_CHROMEOS)
789 #define MAYBE_CopyToBitmap_EntireRegion DISABLED_CopyToBitmap_EntireRegion
790 #define MAYBE_CopyToBitmap_CenterRegion DISABLED_CopyToBitmap_CenterRegion
791 #define MAYBE_CopyToBitmap_ScaledResult DISABLED_CopyToBitmap_ScaledResult
792 #define MAYBE_CopyToVideoFrame_EntireRegion \
793             DISABLED_CopyToVideoFrame_EntireRegion
794 #define MAYBE_CopyToVideoFrame_CenterRegion \
795             DISABLED_CopyToVideoFrame_CenterRegion
796 #define MAYBE_CopyToVideoFrame_ScaledResult \
797             DISABLED_CopyToVideoFrame_ScaledResult
798 #else
799 #define MAYBE_CopyToBitmap_EntireRegion CopyToBitmap_EntireRegion
800 #define MAYBE_CopyToBitmap_CenterRegion CopyToBitmap_CenterRegion
801 #define MAYBE_CopyToBitmap_ScaledResult CopyToBitmap_ScaledResult
802 #define MAYBE_CopyToVideoFrame_EntireRegion CopyToVideoFrame_EntireRegion
803 #define MAYBE_CopyToVideoFrame_CenterRegion CopyToVideoFrame_CenterRegion
804 #define MAYBE_CopyToVideoFrame_ScaledResult CopyToVideoFrame_ScaledResult
805 #endif
806
807 IN_PROC_BROWSER_TEST_P(
808     CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
809     MAYBE_CopyToBitmap_EntireRegion) {
810   gfx::Size html_rect_size(200, 150);
811   gfx::Rect copy_rect(200, 150);
812   // Scale the output size so that, internally, scaling is not occurring.
813   gfx::Size output_size =
814       gfx::ToRoundedSize(gfx::ScaleSize(copy_rect.size(), scale()));
815   bool video_frame = false;
816   PerformTestWithLeftRightRects(html_rect_size,
817                                 copy_rect,
818                                 output_size,
819                                 video_frame);
820 }
821
822 IN_PROC_BROWSER_TEST_P(
823     CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
824     MAYBE_CopyToBitmap_CenterRegion) {
825   gfx::Size html_rect_size(200, 150);
826   // Grab 90x60 pixels from the center of the tab contents.
827   gfx::Rect copy_rect =
828       gfx::Rect(gfx::Rect(html_rect_size).CenterPoint() - gfx::Vector2d(45, 30),
829                 gfx::Size(90, 60));
830   // Scale the output size so that, internally, scaling is not occurring.
831   gfx::Size output_size =
832       gfx::ToRoundedSize(gfx::ScaleSize(copy_rect.size(), scale()));
833   bool video_frame = false;
834   PerformTestWithLeftRightRects(html_rect_size,
835                                 copy_rect,
836                                 output_size,
837                                 video_frame);
838 }
839
840 IN_PROC_BROWSER_TEST_P(
841     CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
842     MAYBE_CopyToBitmap_ScaledResult) {
843   gfx::Size html_rect_size(200, 100);
844   gfx::Rect copy_rect(200, 100);
845   // Output is being down-scaled since output_size is in phyiscal pixels.
846   gfx::Size output_size(200, 100);
847   bool video_frame = false;
848   PerformTestWithLeftRightRects(html_rect_size,
849                                 copy_rect,
850                                 output_size,
851                                 video_frame);
852 }
853
854 IN_PROC_BROWSER_TEST_P(
855     CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
856     MAYBE_CopyToVideoFrame_EntireRegion) {
857   gfx::Size html_rect_size(200, 150);
858   gfx::Rect copy_rect(200, 150);
859   // Scale the output size so that, internally, scaling is not occurring.
860   gfx::Size output_size =
861       gfx::ToRoundedSize(gfx::ScaleSize(copy_rect.size(), scale()));
862   bool video_frame = true;
863   PerformTestWithLeftRightRects(html_rect_size,
864                                 copy_rect,
865                                 output_size,
866                                 video_frame);
867 }
868
869 IN_PROC_BROWSER_TEST_P(
870     CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
871     MAYBE_CopyToVideoFrame_CenterRegion) {
872   gfx::Size html_rect_size(200, 150);
873   // Grab 90x60 pixels from the center of the tab contents.
874   gfx::Rect copy_rect =
875       gfx::Rect(gfx::Rect(html_rect_size).CenterPoint() - gfx::Vector2d(45, 30),
876                 gfx::Size(90, 60));
877   // Scale the output size so that, internally, scaling is not occurring.
878   gfx::Size output_size =
879       gfx::ToRoundedSize(gfx::ScaleSize(copy_rect.size(), scale()));
880   bool video_frame = true;
881   PerformTestWithLeftRightRects(html_rect_size,
882                                 copy_rect,
883                                 output_size,
884                                 video_frame);
885 }
886
887 IN_PROC_BROWSER_TEST_P(
888     CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
889     MAYBE_CopyToVideoFrame_ScaledResult) {
890   gfx::Size html_rect_size(200, 100);
891   gfx::Rect copy_rect(200, 100);
892   // Output is being down-scaled since output_size is in phyiscal pixels.
893   gfx::Size output_size(200, 100);
894   bool video_frame = true;
895   PerformTestWithLeftRightRects(html_rect_size,
896                                 copy_rect,
897                                 output_size,
898                                 video_frame);
899 }
900
901 INSTANTIATE_TEST_CASE_P(GLAndSoftwareCompositing,
902                         CompositingRenderWidgetHostViewBrowserTest,
903                         testing::Values(GL_COMPOSITING, SOFTWARE_COMPOSITING));
904 INSTANTIATE_TEST_CASE_P(GLAndSoftwareCompositing,
905                         CompositingRenderWidgetHostViewBrowserTestTabCapture,
906                         testing::Values(GL_COMPOSITING, SOFTWARE_COMPOSITING));
907 INSTANTIATE_TEST_CASE_P(
908     GLAndSoftwareCompositing,
909     CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
910     testing::Values(GL_COMPOSITING, SOFTWARE_COMPOSITING));
911
912 #endif  // !defined(OS_ANDROID) && !defined(OS_IOS)
913
914 }  // namespace
915 }  // namespace content