- add sources.
[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/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"
35
36 #if defined(OS_MACOSX)
37 #include "ui/gl/io_surface_support_mac.h"
38 #endif
39
40 #if defined(OS_WIN)
41 #include "base/win/windows_version.h"
42 #include "ui/gfx/win/dpi.h"
43 #endif
44
45 namespace content {
46 namespace {
47
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;  \
56   }
57
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;  \
66   }
67
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) {}
77
78   virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
79     ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &test_dir_));
80     ContentBrowserTest::SetUpInProcessBrowserTestFixture();
81   }
82
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;
86
87   int callback_invoke_count() const {
88     return callback_invoke_count_;
89   }
90
91   int frames_captured() const {
92     return frames_captured_;
93   }
94
95   const gfx::Size& frame_size() const {
96     return frame_size_;
97   }
98
99   const base::FilePath& test_dir() const {
100     return test_dir_;
101   }
102
103   RenderViewHost* GetRenderViewHost() const {
104     RenderViewHost* const rvh = shell()->web_contents()->GetRenderViewHost();
105     CHECK(rvh);
106     return rvh;
107   }
108
109   RenderWidgetHostImpl* GetRenderWidgetHost() const {
110     RenderWidgetHostImpl* const rwh = RenderWidgetHostImpl::From(
111         shell()->web_contents()->GetRenderWidgetHostView()->
112             GetRenderWidgetHost());
113     CHECK(rwh);
114     return rwh;
115   }
116
117   RenderWidgetHostViewPort* GetRenderWidgetHostViewPort() const {
118     RenderWidgetHostViewPort* const view =
119         RenderWidgetHostViewPort::FromRWHV(GetRenderViewHost()->GetView());
120     CHECK(view);
121     return view;
122   }
123
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());
132     }
133     if (!quit_closure.is_null())
134       quit_closure.Run();
135   }
136
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();
145   }
146
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);
157   }
158
159   // Copy one frame using the CopyFromBackingStore API.
160   void RunBasicCopyFromBackingStoreTest() {
161     SET_UP_SURFACE_OR_PASS_TEST(NULL);
162
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();
178
179       if (frames_captured())
180         break;
181       else
182         GiveItSomeTime();
183     }
184
185     EXPECT_EQ(count_attempts, callback_invoke_count());
186     EXPECT_EQ(1, frames_captured());
187   }
188
189  protected:
190   // Waits until the source is available for copying.
191   void WaitForCopySourceReady() {
192     while (!GetRenderWidgetHostViewPort()->IsSurfaceAvailableForCopy())
193       GiveItSomeTime();
194   }
195
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();
205   }
206
207  private:
208   const gfx::Size frame_size_;
209   base::FilePath test_dir_;
210   int callback_invoke_count_;
211   int frames_captured_;
212 };
213
214 class CompositingRenderWidgetHostViewBrowserTest
215     : public RenderWidgetHostViewBrowserTest {
216  public:
217   virtual void SetUp() OVERRIDE {
218     // We expect real pixel output for these tests.
219     UseRealGLContexts();
220
221     // On legacy windows, these tests need real GL bindings to pass.
222 #if defined(OS_WIN) && !defined(USE_AURA)
223     UseRealGLBindings();
224 #endif
225
226     RenderWidgetHostViewBrowserTest::SetUp();
227   }
228
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);
237   }
238
239   virtual GURL TestUrl() {
240     return net::FilePathToFileURL(
241         test_dir().AppendASCII("rwhv_compositing_animation.html"));
242   }
243
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
250
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;
258       }
259     }
260
261 #if !defined(USE_AURA)
262     if (!GetRenderWidgetHost()->is_accelerated_compositing_active())
263       return false;  // Renderer did not turn on accelerated compositing.
264 #endif
265
266     // Using accelerated compositing, but a compositing surface might not be
267     // available yet.  So, wait for it.
268     WaitForCopySourceReady();
269     return true;
270   }
271 };
272
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);
285   }
286
287   virtual GURL TestUrl() {
288     return GURL(kAboutBlankURL);
289   }
290
291   virtual bool SetUpSourceSurface(const char* wait_message) OVERRIDE {
292     if (IsForceCompositingModeEnabled())
293       return false;  // See comment in SetUpCommandLine().
294
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;
302       }
303     }
304
305     WaitForCopySourceReady();
306     // Return whether the renderer left accelerated compositing turned off.
307     return !GetRenderWidgetHost()->is_accelerated_compositing_active();
308   }
309 };
310
311 class FakeFrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
312  public:
313   FakeFrameSubscriber(
314     RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback)
315       : callback_(callback) {
316   }
317
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;
333   }
334
335  private:
336   DeliverFrameCallback callback_;
337 };
338
339 // Disable tests for Android and IOS as these platforms have incomplete
340 // implementation.
341 #if !defined(OS_ANDROID) && !defined(OS_IOS)
342
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();
348 }
349
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();
355 }
356
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);
362
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();
372
373   EXPECT_EQ(1, callback_invoke_count());
374 }
375
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.
379 //
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;
398   }
399
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();
410
411   EXPECT_EQ(1, callback_invoke_count());
412 }
413
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());
420 }
421
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;
432   }
433
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();
444
445   EXPECT_LE(1, callback_invoke_count());
446   EXPECT_LE(1, frames_captured());
447 }
448
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;
458   }
459
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();
483
484   EXPECT_EQ(2, callback_invoke_count());
485   EXPECT_EQ(2, frames_captured());
486 }
487
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>") {}
495
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;
503     }
504
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;
517
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;
548       }
549     }
550     EXPECT_LT(fails, 10);
551
552     quit_callback.Run();
553   }
554
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;
563     }
564
565     media::SkCanvasVideoRenderer video_renderer;
566
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();
573
574     SkBitmapDevice device(bitmap);
575     SkCanvas canvas(&device);
576
577     video_renderer.Paint(video_frame.get(),
578                          &canvas,
579                          video_frame->visible_rect(),
580                          0xff);
581
582     CopyFromCompositingSurfaceCallback(quit_callback,
583                                        result,
584                                        bitmap);
585   }
586
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;
591   }
592
593   void SetAllowableError(int amount) { allowable_error_ = amount; }
594   void SetExcludeRect(gfx::Rect exclude) { exclude_rect_ = exclude; }
595
596   virtual GURL TestUrl() OVERRIDE {
597     return GURL(test_url_);
598   }
599
600   void SetTestUrl(std::string url) { test_url_ = url; }
601
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;"
628         "}"
629         ".right { position: absolute;"
630         "         left: %dpx;"
631         "         background: #ff0;"
632         "         width: %dpx;"
633         "         height: %dpx;"
634         "}"
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()));
645
646     SET_UP_SURFACE_OR_PASS_TEST("\"DONE\"");
647     if (!ShouldContinueAfterTestURLLoad())
648       return;
649
650     RenderWidgetHostViewPort* rwhvp = GetRenderWidgetHostViewPort();
651
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();
658
659     SkBitmap expected_bitmap;
660     SetupLeftRightBitmap(expected_bitmap_size, &expected_bitmap);
661     SetExpectedCopyFromCompositingSurfaceResult(true, expected_bitmap);
662
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()));
670
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());
677
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()));
696       }
697 #endif
698
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);
705     }
706     run_loop.Run();
707   }
708
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.
718     {
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);
724         }
725       }
726     }
727   }
728
729  protected:
730   virtual bool ShouldContinueAfterTestURLLoad() {
731     return true;
732   }
733
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_;
740 };
741
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);
754 }
755
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);
768 }
769
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);
785 }
786
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);
802 }
803
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);
819 }
820
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);
837 }
838
839 class CompositingRenderWidgetHostViewTabCaptureHighDPI
840     : public CompositingRenderWidgetHostViewBrowserTestTabCapture {
841  public:
842   CompositingRenderWidgetHostViewTabCaptureHighDPI()
843       : kScale(2.f) {
844   }
845
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
854   }
855
856   float scale() const { return kScale; }
857
858  private:
859   virtual bool ShouldContinueAfterTestURLLoad() OVERRIDE {
860     PASS_TEST_IF_SCALE_FACTOR_NOT_SUPPORTED(scale());
861     return true;
862   }
863
864   const float kScale;
865
866   DISALLOW_COPY_AND_ASSIGN(CompositingRenderWidgetHostViewTabCaptureHighDPI);
867 };
868
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);
882 }
883
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);
900 }
901
902 #endif  // !defined(OS_ANDROID) && !defined(OS_IOS)
903
904 }  // namespace
905 }  // namespace content