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