Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / render_widget_host_view_aura_unittest.cc
1 // Copyright (c) 2012 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 "content/browser/renderer_host/render_widget_host_view_aura.h"
6
7 #include "base/basictypes.h"
8 #include "base/memory/shared_memory.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/run_loop.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "cc/output/compositor_frame.h"
13 #include "cc/output/compositor_frame_metadata.h"
14 #include "cc/output/copy_output_request.h"
15 #include "cc/output/gl_frame_data.h"
16 #include "content/browser/browser_thread_impl.h"
17 #include "content/browser/compositor/resize_lock.h"
18 #include "content/browser/renderer_host/render_widget_host_delegate.h"
19 #include "content/browser/renderer_host/render_widget_host_impl.h"
20 #include "content/common/gpu/gpu_messages.h"
21 #include "content/common/input_messages.h"
22 #include "content/common/view_messages.h"
23 #include "content/port/browser/render_widget_host_view_frame_subscriber.h"
24 #include "content/public/browser/render_widget_host_view.h"
25 #include "content/public/test/mock_render_process_host.h"
26 #include "content/public/test/test_browser_context.h"
27 #include "ipc/ipc_test_sink.h"
28 #include "testing/gmock/include/gmock/gmock.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "ui/aura/client/aura_constants.h"
31 #include "ui/aura/client/screen_position_client.h"
32 #include "ui/aura/client/window_tree_client.h"
33 #include "ui/aura/env.h"
34 #include "ui/aura/layout_manager.h"
35 #include "ui/aura/root_window.h"
36 #include "ui/aura/test/aura_test_helper.h"
37 #include "ui/aura/test/event_generator.h"
38 #include "ui/aura/test/test_cursor_client.h"
39 #include "ui/aura/test/test_screen.h"
40 #include "ui/aura/test/test_window_delegate.h"
41 #include "ui/aura/window.h"
42 #include "ui/aura/window_observer.h"
43 #include "ui/base/ui_base_types.h"
44 #include "ui/compositor/compositor.h"
45 #include "ui/compositor/test/draw_waiter_for_test.h"
46 #include "ui/compositor/test/test_context_factory.h"
47 #include "ui/events/event.h"
48 #include "ui/events/event_utils.h"
49
50 using testing::_;
51
52 namespace content {
53 namespace {
54
55 // Simple screen position client to test coordinate system conversion.
56 class TestScreenPositionClient
57     : public aura::client::ScreenPositionClient {
58  public:
59   TestScreenPositionClient() {}
60   virtual ~TestScreenPositionClient() {}
61
62   // aura::client::ScreenPositionClient overrides:
63   virtual void ConvertPointToScreen(const aura::Window* window,
64       gfx::Point* point) OVERRIDE {
65     point->Offset(-1, -1);
66   }
67
68   virtual void ConvertPointFromScreen(const aura::Window* window,
69       gfx::Point* point) OVERRIDE {
70     point->Offset(1, 1);
71   }
72
73   virtual void ConvertHostPointToScreen(aura::Window* window,
74       gfx::Point* point) OVERRIDE {
75     ConvertPointToScreen(window, point);
76   }
77
78   virtual void SetBounds(aura::Window* window,
79       const gfx::Rect& bounds,
80       const gfx::Display& display) OVERRIDE {
81   }
82 };
83
84 class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
85  public:
86   MockRenderWidgetHostDelegate() {}
87   virtual ~MockRenderWidgetHostDelegate() {}
88 };
89
90 // Simple observer that keeps track of changes to a window for tests.
91 class TestWindowObserver : public aura::WindowObserver {
92  public:
93   explicit TestWindowObserver(aura::Window* window_to_observe)
94       : window_(window_to_observe) {
95     window_->AddObserver(this);
96   }
97   virtual ~TestWindowObserver() {
98     if (window_)
99       window_->RemoveObserver(this);
100   }
101
102   bool destroyed() const { return destroyed_; }
103
104   // aura::WindowObserver overrides:
105   virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE {
106     CHECK_EQ(window, window_);
107     destroyed_ = true;
108     window_ = NULL;
109   }
110
111  private:
112   // Window that we're observing, or NULL if it's been destroyed.
113   aura::Window* window_;
114
115   // Was |window_| destroyed?
116   bool destroyed_;
117
118   DISALLOW_COPY_AND_ASSIGN(TestWindowObserver);
119 };
120
121 class FakeFrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
122  public:
123   FakeFrameSubscriber(gfx::Size size, base::Callback<void(bool)> callback)
124       : size_(size), callback_(callback) {}
125
126   virtual bool ShouldCaptureFrame(base::TimeTicks present_time,
127                                   scoped_refptr<media::VideoFrame>* storage,
128                                   DeliverFrameCallback* callback) OVERRIDE {
129     *storage = media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
130                                               size_,
131                                               gfx::Rect(size_),
132                                               size_,
133                                               base::TimeDelta());
134     *callback = base::Bind(&FakeFrameSubscriber::CallbackMethod, callback_);
135     return true;
136   }
137
138   static void CallbackMethod(base::Callback<void(bool)> callback,
139                              base::TimeTicks timestamp,
140                              bool success) {
141     callback.Run(success);
142   }
143
144  private:
145   gfx::Size size_;
146   base::Callback<void(bool)> callback_;
147 };
148
149 class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
150  public:
151   FakeRenderWidgetHostViewAura(RenderWidgetHost* widget)
152       : RenderWidgetHostViewAura(widget), has_resize_lock_(false) {}
153
154   virtual ~FakeRenderWidgetHostViewAura() {}
155
156   virtual bool ShouldCreateResizeLock() OVERRIDE {
157     gfx::Size desired_size = window()->bounds().size();
158     return desired_size != current_frame_size();
159   }
160
161   virtual scoped_ptr<ResizeLock> CreateResizeLock(bool defer_compositor_lock)
162       OVERRIDE {
163     gfx::Size desired_size = window()->bounds().size();
164     return scoped_ptr<ResizeLock>(
165         new FakeResizeLock(desired_size, defer_compositor_lock));
166   }
167
168   virtual void RequestCopyOfOutput(scoped_ptr<cc::CopyOutputRequest> request)
169       OVERRIDE {
170     last_copy_request_ = request.Pass();
171   }
172
173   void RunOnCompositingDidCommit() {
174     OnCompositingDidCommit(window()->GetDispatcher()->host()->compositor());
175   }
176
177   // A lock that doesn't actually do anything to the compositor, and does not
178   // time out.
179   class FakeResizeLock : public ResizeLock {
180    public:
181     FakeResizeLock(const gfx::Size new_size, bool defer_compositor_lock)
182         : ResizeLock(new_size, defer_compositor_lock) {}
183   };
184
185   bool has_resize_lock_;
186   gfx::Size last_frame_size_;
187   scoped_ptr<cc::CopyOutputRequest> last_copy_request_;
188 };
189
190 class RenderWidgetHostViewAuraTest : public testing::Test {
191  public:
192   RenderWidgetHostViewAuraTest()
193       : browser_thread_for_ui_(BrowserThread::UI, &message_loop_) {}
194
195   void SetUpEnvironment() {
196     ImageTransportFactory::InitializeForUnitTests(
197         scoped_ptr<ui::ContextFactory>(new ui::TestContextFactory));
198     aura_test_helper_.reset(new aura::test::AuraTestHelper(&message_loop_));
199     bool allow_test_contexts = true;
200     aura_test_helper_->SetUp(allow_test_contexts);
201
202     browser_context_.reset(new TestBrowserContext);
203     process_host_ = new MockRenderProcessHost(browser_context_.get());
204
205     sink_ = &process_host_->sink();
206
207     parent_host_ = new RenderWidgetHostImpl(
208         &delegate_, process_host_, MSG_ROUTING_NONE, false);
209     parent_view_ = static_cast<RenderWidgetHostViewAura*>(
210         RenderWidgetHostView::CreateViewForWidget(parent_host_));
211     parent_view_->InitAsChild(NULL);
212     aura::client::ParentWindowWithContext(parent_view_->GetNativeView(),
213                                           aura_test_helper_->root_window(),
214                                           gfx::Rect());
215
216     widget_host_ = new RenderWidgetHostImpl(
217         &delegate_, process_host_, MSG_ROUTING_NONE, false);
218     widget_host_->Init();
219     widget_host_->OnMessageReceived(
220         ViewHostMsg_DidActivateAcceleratedCompositing(0, true));
221     view_ = new FakeRenderWidgetHostViewAura(widget_host_);
222   }
223
224   void TearDownEnvironment() {
225     sink_ = NULL;
226     process_host_ = NULL;
227     if (view_)
228       view_->Destroy();
229     delete widget_host_;
230
231     parent_view_->Destroy();
232     delete parent_host_;
233
234     browser_context_.reset();
235     aura_test_helper_->TearDown();
236
237     message_loop_.DeleteSoon(FROM_HERE, browser_context_.release());
238     message_loop_.RunUntilIdle();
239     ImageTransportFactory::Terminate();
240   }
241
242   virtual void SetUp() { SetUpEnvironment(); }
243
244   virtual void TearDown() { TearDownEnvironment(); }
245
246  protected:
247   base::MessageLoopForUI message_loop_;
248   BrowserThreadImpl browser_thread_for_ui_;
249   scoped_ptr<aura::test::AuraTestHelper> aura_test_helper_;
250   scoped_ptr<BrowserContext> browser_context_;
251   MockRenderWidgetHostDelegate delegate_;
252   MockRenderProcessHost* process_host_;
253
254   // Tests should set these to NULL if they've already triggered their
255   // destruction.
256   RenderWidgetHostImpl* parent_host_;
257   RenderWidgetHostViewAura* parent_view_;
258
259   // Tests should set these to NULL if they've already triggered their
260   // destruction.
261   RenderWidgetHostImpl* widget_host_;
262   FakeRenderWidgetHostViewAura* view_;
263
264   IPC::TestSink* sink_;
265
266  private:
267   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAuraTest);
268 };
269
270 class RenderWidgetHostViewAuraShutdownTest
271     : public RenderWidgetHostViewAuraTest {
272  public:
273   RenderWidgetHostViewAuraShutdownTest() {}
274
275   virtual void TearDown() OVERRIDE {
276     // No TearDownEnvironment here, we do this explicitly during the test.
277   }
278
279  private:
280   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAuraShutdownTest);
281 };
282
283 // A layout manager that always resizes a child to the root window size.
284 class FullscreenLayoutManager : public aura::LayoutManager {
285  public:
286   explicit FullscreenLayoutManager(aura::Window* owner)
287       : owner_(owner) {}
288   virtual ~FullscreenLayoutManager() {}
289
290   // Overridden from aura::LayoutManager:
291   virtual void OnWindowResized() OVERRIDE {
292     aura::Window::Windows::const_iterator i;
293     for (i = owner_->children().begin(); i != owner_->children().end(); ++i) {
294       (*i)->SetBounds(gfx::Rect());
295     }
296   }
297   virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE {
298     child->SetBounds(gfx::Rect());
299   }
300   virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {
301   }
302   virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE {
303   }
304   virtual void OnChildWindowVisibilityChanged(aura::Window* child,
305                                               bool visible) OVERRIDE {
306   }
307   virtual void SetChildBounds(aura::Window* child,
308                               const gfx::Rect& requested_bounds) OVERRIDE {
309     SetChildBoundsDirect(child, gfx::Rect(owner_->bounds().size()));
310   }
311
312  private:
313   aura::Window* owner_;
314   DISALLOW_COPY_AND_ASSIGN(FullscreenLayoutManager);
315 };
316
317 class MockWindowObserver : public aura::WindowObserver {
318  public:
319   MOCK_METHOD2(OnWindowPaintScheduled, void(aura::Window*, const gfx::Rect&));
320 };
321
322 }  // namespace
323
324 // Checks that a fullscreen view has the correct show-state and receives the
325 // focus.
326 TEST_F(RenderWidgetHostViewAuraTest, FocusFullscreen) {
327   view_->InitAsFullscreen(parent_view_);
328   aura::Window* window = view_->GetNativeView();
329   ASSERT_TRUE(window != NULL);
330   EXPECT_EQ(ui::SHOW_STATE_FULLSCREEN,
331             window->GetProperty(aura::client::kShowStateKey));
332
333   // Check that we requested and received the focus.
334   EXPECT_TRUE(window->HasFocus());
335
336   // Check that we'll also say it's okay to activate the window when there's an
337   // ActivationClient defined.
338   EXPECT_TRUE(view_->ShouldActivate());
339 }
340
341 // Checks that a popup is positioned correctly relative to its parent using
342 // screen coordinates.
343 TEST_F(RenderWidgetHostViewAuraTest, PositionChildPopup) {
344   TestScreenPositionClient screen_position_client;
345
346   aura::Window* window = parent_view_->GetNativeView();
347   aura::Window* root = window->GetRootWindow();
348   aura::client::SetScreenPositionClient(root, &screen_position_client);
349
350   parent_view_->SetBounds(gfx::Rect(10, 10, 800, 600));
351   gfx::Rect bounds_in_screen = parent_view_->GetViewBounds();
352   int horiz = bounds_in_screen.width() / 4;
353   int vert = bounds_in_screen.height() / 4;
354   bounds_in_screen.Inset(horiz, vert);
355
356   // Verify that when the popup is initialized for the first time, it correctly
357   // treats the input bounds as screen coordinates.
358   view_->InitAsPopup(parent_view_, bounds_in_screen);
359
360   gfx::Rect final_bounds_in_screen = view_->GetViewBounds();
361   EXPECT_EQ(final_bounds_in_screen.ToString(), bounds_in_screen.ToString());
362
363   // Verify that directly setting the bounds via SetBounds() treats the input
364   // as screen coordinates.
365   bounds_in_screen = gfx::Rect(60, 60, 100, 100);
366   view_->SetBounds(bounds_in_screen);
367   final_bounds_in_screen = view_->GetViewBounds();
368   EXPECT_EQ(final_bounds_in_screen.ToString(), bounds_in_screen.ToString());
369
370   // Verify that setting the size does not alter the origin.
371   gfx::Point original_origin = window->bounds().origin();
372   view_->SetSize(gfx::Size(120, 120));
373   gfx::Point new_origin = window->bounds().origin();
374   EXPECT_EQ(original_origin.ToString(), new_origin.ToString());
375
376   aura::client::SetScreenPositionClient(root, NULL);
377 }
378
379 // Checks that a fullscreen view is destroyed when it loses the focus.
380 TEST_F(RenderWidgetHostViewAuraTest, DestroyFullscreenOnBlur) {
381   view_->InitAsFullscreen(parent_view_);
382   aura::Window* window = view_->GetNativeView();
383   ASSERT_TRUE(window != NULL);
384   ASSERT_TRUE(window->HasFocus());
385
386   // After we create and focus another window, the RWHVA's window should be
387   // destroyed.
388   TestWindowObserver observer(window);
389   aura::test::TestWindowDelegate delegate;
390   scoped_ptr<aura::Window> sibling(new aura::Window(&delegate));
391   sibling->Init(aura::WINDOW_LAYER_TEXTURED);
392   sibling->Show();
393   window->parent()->AddChild(sibling.get());
394   sibling->Focus();
395   ASSERT_TRUE(sibling->HasFocus());
396   ASSERT_TRUE(observer.destroyed());
397
398   widget_host_ = NULL;
399   view_ = NULL;
400 }
401
402 // Checks that a popup view is destroyed when a user clicks outside of the popup
403 // view and focus does not change. This is the case when the user clicks on the
404 // desktop background on Chrome OS.
405 TEST_F(RenderWidgetHostViewAuraTest, DestroyPopupClickOutsidePopup) {
406   parent_view_->SetBounds(gfx::Rect(10, 10, 400, 400));
407   parent_view_->Focus();
408   EXPECT_TRUE(parent_view_->HasFocus());
409
410   view_->InitAsPopup(parent_view_, gfx::Rect(10, 10, 100, 100));
411   aura::Window* window = view_->GetNativeView();
412   ASSERT_TRUE(window != NULL);
413
414   gfx::Point click_point;
415   EXPECT_FALSE(window->GetBoundsInRootWindow().Contains(click_point));
416   aura::Window* parent_window = parent_view_->GetNativeView();
417   EXPECT_FALSE(parent_window->GetBoundsInRootWindow().Contains(click_point));
418
419   TestWindowObserver observer(window);
420   aura::test::EventGenerator generator(window->GetRootWindow(), click_point);
421   generator.ClickLeftButton();
422   ASSERT_TRUE(parent_view_->HasFocus());
423   ASSERT_TRUE(observer.destroyed());
424
425   widget_host_ = NULL;
426   view_ = NULL;
427 }
428
429 // Checks that a popup view is destroyed when a user taps outside of the popup
430 // view and focus does not change. This is the case when the user taps the
431 // desktop background on Chrome OS.
432 TEST_F(RenderWidgetHostViewAuraTest, DestroyPopupTapOutsidePopup) {
433   parent_view_->SetBounds(gfx::Rect(10, 10, 400, 400));
434   parent_view_->Focus();
435   EXPECT_TRUE(parent_view_->HasFocus());
436
437   view_->InitAsPopup(parent_view_, gfx::Rect(10, 10, 100, 100));
438   aura::Window* window = view_->GetNativeView();
439   ASSERT_TRUE(window != NULL);
440
441   gfx::Point tap_point;
442   EXPECT_FALSE(window->GetBoundsInRootWindow().Contains(tap_point));
443   aura::Window* parent_window = parent_view_->GetNativeView();
444   EXPECT_FALSE(parent_window->GetBoundsInRootWindow().Contains(tap_point));
445
446   TestWindowObserver observer(window);
447   aura::test::EventGenerator generator(window->GetRootWindow(), tap_point);
448   generator.GestureTapAt(tap_point);
449   ASSERT_TRUE(parent_view_->HasFocus());
450   ASSERT_TRUE(observer.destroyed());
451
452   widget_host_ = NULL;
453   view_ = NULL;
454 }
455
456 // Checks that IME-composition-event state is maintained correctly.
457 TEST_F(RenderWidgetHostViewAuraTest, SetCompositionText) {
458   view_->InitAsChild(NULL);
459   view_->Show();
460
461   ui::CompositionText composition_text;
462   composition_text.text = base::ASCIIToUTF16("|a|b");
463
464   // Focused segment
465   composition_text.underlines.push_back(
466       ui::CompositionUnderline(0, 3, 0xff000000, true));
467
468   // Non-focused segment
469   composition_text.underlines.push_back(
470       ui::CompositionUnderline(3, 4, 0xff000000, false));
471
472   const ui::CompositionUnderlines& underlines = composition_text.underlines;
473
474   // Caret is at the end. (This emulates Japanese MSIME 2007 and later)
475   composition_text.selection = gfx::Range(4);
476
477   sink_->ClearMessages();
478   view_->SetCompositionText(composition_text);
479   EXPECT_TRUE(view_->has_composition_text_);
480   {
481     const IPC::Message* msg =
482       sink_->GetFirstMessageMatching(ViewMsg_ImeSetComposition::ID);
483     ASSERT_TRUE(msg != NULL);
484
485     ViewMsg_ImeSetComposition::Param params;
486     ViewMsg_ImeSetComposition::Read(msg, &params);
487     // composition text
488     EXPECT_EQ(composition_text.text, params.a);
489     // underlines
490     ASSERT_EQ(underlines.size(), params.b.size());
491     for (size_t i = 0; i < underlines.size(); ++i) {
492       EXPECT_EQ(underlines[i].start_offset, params.b[i].startOffset);
493       EXPECT_EQ(underlines[i].end_offset, params.b[i].endOffset);
494       EXPECT_EQ(underlines[i].color, params.b[i].color);
495       EXPECT_EQ(underlines[i].thick, params.b[i].thick);
496     }
497     // highlighted range
498     EXPECT_EQ(4, params.c) << "Should be the same to the caret pos";
499     EXPECT_EQ(4, params.d) << "Should be the same to the caret pos";
500   }
501
502   view_->ImeCancelComposition();
503   EXPECT_FALSE(view_->has_composition_text_);
504 }
505
506 // Checks that touch-event state is maintained correctly.
507 TEST_F(RenderWidgetHostViewAuraTest, TouchEventState) {
508   view_->InitAsChild(NULL);
509   view_->Show();
510
511   // Start with no touch-event handler in the renderer.
512   widget_host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false));
513   EXPECT_FALSE(widget_host_->ShouldForwardTouchEvent());
514
515   ui::TouchEvent press(ui::ET_TOUCH_PRESSED,
516                        gfx::Point(30, 30),
517                        0,
518                        ui::EventTimeForNow());
519   ui::TouchEvent move(ui::ET_TOUCH_MOVED,
520                       gfx::Point(20, 20),
521                       0,
522                       ui::EventTimeForNow());
523   ui::TouchEvent release(ui::ET_TOUCH_RELEASED,
524                          gfx::Point(20, 20),
525                          0,
526                          ui::EventTimeForNow());
527
528   view_->OnTouchEvent(&press);
529   EXPECT_FALSE(press.handled());
530   EXPECT_EQ(blink::WebInputEvent::TouchStart, view_->touch_event_.type);
531   EXPECT_EQ(1U, view_->touch_event_.touchesLength);
532   EXPECT_EQ(blink::WebTouchPoint::StatePressed,
533             view_->touch_event_.touches[0].state);
534
535   view_->OnTouchEvent(&move);
536   EXPECT_FALSE(move.handled());
537   EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_.type);
538   EXPECT_EQ(1U, view_->touch_event_.touchesLength);
539   EXPECT_EQ(blink::WebTouchPoint::StateMoved,
540             view_->touch_event_.touches[0].state);
541
542   view_->OnTouchEvent(&release);
543   EXPECT_FALSE(release.handled());
544   EXPECT_EQ(blink::WebInputEvent::TouchEnd, view_->touch_event_.type);
545   EXPECT_EQ(0U, view_->touch_event_.touchesLength);
546
547   // Now install some touch-event handlers and do the same steps. The touch
548   // events should now be consumed. However, the touch-event state should be
549   // updated as before.
550   widget_host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true));
551   EXPECT_TRUE(widget_host_->ShouldForwardTouchEvent());
552
553   view_->OnTouchEvent(&press);
554   EXPECT_TRUE(press.stopped_propagation());
555   EXPECT_EQ(blink::WebInputEvent::TouchStart, view_->touch_event_.type);
556   EXPECT_EQ(1U, view_->touch_event_.touchesLength);
557   EXPECT_EQ(blink::WebTouchPoint::StatePressed,
558             view_->touch_event_.touches[0].state);
559
560   view_->OnTouchEvent(&move);
561   EXPECT_TRUE(move.stopped_propagation());
562   EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_.type);
563   EXPECT_EQ(1U, view_->touch_event_.touchesLength);
564   EXPECT_EQ(blink::WebTouchPoint::StateMoved,
565             view_->touch_event_.touches[0].state);
566
567   view_->OnTouchEvent(&release);
568   EXPECT_TRUE(release.stopped_propagation());
569   EXPECT_EQ(blink::WebInputEvent::TouchEnd, view_->touch_event_.type);
570   EXPECT_EQ(0U, view_->touch_event_.touchesLength);
571
572   // Now start a touch event, and remove the event-handlers before the release.
573   view_->OnTouchEvent(&press);
574   EXPECT_TRUE(press.stopped_propagation());
575   EXPECT_EQ(blink::WebInputEvent::TouchStart, view_->touch_event_.type);
576   EXPECT_EQ(1U, view_->touch_event_.touchesLength);
577   EXPECT_EQ(blink::WebTouchPoint::StatePressed,
578             view_->touch_event_.touches[0].state);
579
580   widget_host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false));
581   EXPECT_FALSE(widget_host_->ShouldForwardTouchEvent());
582
583   ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(20, 20), 0,
584       base::Time::NowFromSystemTime() - base::Time());
585   view_->OnTouchEvent(&move2);
586   EXPECT_FALSE(move2.handled());
587   EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_.type);
588   EXPECT_EQ(1U, view_->touch_event_.touchesLength);
589   EXPECT_EQ(blink::WebTouchPoint::StateMoved,
590             view_->touch_event_.touches[0].state);
591
592   ui::TouchEvent release2(ui::ET_TOUCH_RELEASED, gfx::Point(20, 20), 0,
593       base::Time::NowFromSystemTime() - base::Time());
594   view_->OnTouchEvent(&release2);
595   EXPECT_FALSE(release2.handled());
596   EXPECT_EQ(blink::WebInputEvent::TouchEnd, view_->touch_event_.type);
597   EXPECT_EQ(0U, view_->touch_event_.touchesLength);
598 }
599
600 // Checks that touch-events are queued properly when there is a touch-event
601 // handler on the page.
602 TEST_F(RenderWidgetHostViewAuraTest, TouchEventSyncAsync) {
603   view_->InitAsChild(NULL);
604   view_->Show();
605
606   widget_host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true));
607   EXPECT_TRUE(widget_host_->ShouldForwardTouchEvent());
608
609   ui::TouchEvent press(ui::ET_TOUCH_PRESSED,
610                        gfx::Point(30, 30),
611                        0,
612                        ui::EventTimeForNow());
613   ui::TouchEvent move(ui::ET_TOUCH_MOVED,
614                       gfx::Point(20, 20),
615                       0,
616                       ui::EventTimeForNow());
617   ui::TouchEvent release(ui::ET_TOUCH_RELEASED,
618                          gfx::Point(20, 20),
619                          0,
620                          ui::EventTimeForNow());
621
622   view_->OnTouchEvent(&press);
623   EXPECT_TRUE(press.stopped_propagation());
624   EXPECT_EQ(blink::WebInputEvent::TouchStart, view_->touch_event_.type);
625   EXPECT_EQ(1U, view_->touch_event_.touchesLength);
626   EXPECT_EQ(blink::WebTouchPoint::StatePressed,
627             view_->touch_event_.touches[0].state);
628
629   view_->OnTouchEvent(&move);
630   EXPECT_TRUE(move.stopped_propagation());
631   EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_.type);
632   EXPECT_EQ(1U, view_->touch_event_.touchesLength);
633   EXPECT_EQ(blink::WebTouchPoint::StateMoved,
634             view_->touch_event_.touches[0].state);
635
636   // Send the same move event. Since the point hasn't moved, it won't affect the
637   // queue. However, the view should consume the event.
638   view_->OnTouchEvent(&move);
639   EXPECT_TRUE(move.stopped_propagation());
640   EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_.type);
641   EXPECT_EQ(1U, view_->touch_event_.touchesLength);
642   EXPECT_EQ(blink::WebTouchPoint::StateMoved,
643             view_->touch_event_.touches[0].state);
644
645   view_->OnTouchEvent(&release);
646   EXPECT_TRUE(release.stopped_propagation());
647   EXPECT_EQ(blink::WebInputEvent::TouchEnd, view_->touch_event_.type);
648   EXPECT_EQ(0U, view_->touch_event_.touchesLength);
649 }
650
651 TEST_F(RenderWidgetHostViewAuraTest, PhysicalBackingSizeWithScale) {
652   view_->InitAsChild(NULL);
653   aura::client::ParentWindowWithContext(
654       view_->GetNativeView(),
655       parent_view_->GetNativeView()->GetRootWindow(),
656       gfx::Rect());
657   sink_->ClearMessages();
658   view_->SetSize(gfx::Size(100, 100));
659   EXPECT_EQ("100x100", view_->GetPhysicalBackingSize().ToString());
660   EXPECT_EQ(1u, sink_->message_count());
661   EXPECT_EQ(ViewMsg_Resize::ID, sink_->GetMessageAt(0)->type());
662   {
663     const IPC::Message* msg = sink_->GetMessageAt(0);
664     EXPECT_EQ(ViewMsg_Resize::ID, msg->type());
665     ViewMsg_Resize::Param params;
666     ViewMsg_Resize::Read(msg, &params);
667     EXPECT_EQ("100x100", params.a.new_size.ToString());  // dip size
668     EXPECT_EQ("100x100",
669         params.a.physical_backing_size.ToString());  // backing size
670   }
671
672   widget_host_->ResetSizeAndRepaintPendingFlags();
673   sink_->ClearMessages();
674
675   aura_test_helper_->test_screen()->SetDeviceScaleFactor(2.0f);
676   EXPECT_EQ("200x200", view_->GetPhysicalBackingSize().ToString());
677   // Extra ScreenInfoChanged message for |parent_view_|.
678   EXPECT_EQ(1u, sink_->message_count());
679   {
680     const IPC::Message* msg = sink_->GetMessageAt(0);
681     EXPECT_EQ(ViewMsg_Resize::ID, msg->type());
682     ViewMsg_Resize::Param params;
683     ViewMsg_Resize::Read(msg, &params);
684     EXPECT_EQ(2.0f, params.a.screen_info.deviceScaleFactor);
685     EXPECT_EQ("100x100", params.a.new_size.ToString());  // dip size
686     EXPECT_EQ("200x200",
687         params.a.physical_backing_size.ToString());  // backing size
688   }
689
690   widget_host_->ResetSizeAndRepaintPendingFlags();
691   sink_->ClearMessages();
692
693   aura_test_helper_->test_screen()->SetDeviceScaleFactor(1.0f);
694   // Extra ScreenInfoChanged message for |parent_view_|.
695   EXPECT_EQ(1u, sink_->message_count());
696   EXPECT_EQ("100x100", view_->GetPhysicalBackingSize().ToString());
697   {
698     const IPC::Message* msg = sink_->GetMessageAt(0);
699     EXPECT_EQ(ViewMsg_Resize::ID, msg->type());
700     ViewMsg_Resize::Param params;
701     ViewMsg_Resize::Read(msg, &params);
702     EXPECT_EQ(1.0f, params.a.screen_info.deviceScaleFactor);
703     EXPECT_EQ("100x100", params.a.new_size.ToString());  // dip size
704     EXPECT_EQ("100x100",
705         params.a.physical_backing_size.ToString());  // backing size
706   }
707 }
708
709 // Checks that InputMsg_CursorVisibilityChange IPC messages are dispatched
710 // to the renderer at the correct times.
711 TEST_F(RenderWidgetHostViewAuraTest, CursorVisibilityChange) {
712   view_->InitAsChild(NULL);
713   aura::client::ParentWindowWithContext(
714       view_->GetNativeView(),
715       parent_view_->GetNativeView()->GetRootWindow(),
716       gfx::Rect());
717   view_->SetSize(gfx::Size(100, 100));
718
719   aura::test::TestCursorClient cursor_client(
720       parent_view_->GetNativeView()->GetRootWindow());
721
722   cursor_client.AddObserver(view_);
723
724   // Expect a message the first time the cursor is shown.
725   view_->WasShown();
726   sink_->ClearMessages();
727   cursor_client.ShowCursor();
728   EXPECT_EQ(1u, sink_->message_count());
729   EXPECT_TRUE(sink_->GetUniqueMessageMatching(
730       InputMsg_CursorVisibilityChange::ID));
731
732   // No message expected if the renderer already knows the cursor is visible.
733   sink_->ClearMessages();
734   cursor_client.ShowCursor();
735   EXPECT_EQ(0u, sink_->message_count());
736
737   // Hiding the cursor should send a message.
738   sink_->ClearMessages();
739   cursor_client.HideCursor();
740   EXPECT_EQ(1u, sink_->message_count());
741   EXPECT_TRUE(sink_->GetUniqueMessageMatching(
742       InputMsg_CursorVisibilityChange::ID));
743
744   // No message expected if the renderer already knows the cursor is invisible.
745   sink_->ClearMessages();
746   cursor_client.HideCursor();
747   EXPECT_EQ(0u, sink_->message_count());
748
749   // No messages should be sent while the view is invisible.
750   view_->WasHidden();
751   sink_->ClearMessages();
752   cursor_client.ShowCursor();
753   EXPECT_EQ(0u, sink_->message_count());
754   cursor_client.HideCursor();
755   EXPECT_EQ(0u, sink_->message_count());
756
757   // Show the view. Since the cursor was invisible when the view was hidden,
758   // no message should be sent.
759   sink_->ClearMessages();
760   view_->WasShown();
761   EXPECT_FALSE(sink_->GetUniqueMessageMatching(
762       InputMsg_CursorVisibilityChange::ID));
763
764   // No message expected if the renderer already knows the cursor is invisible.
765   sink_->ClearMessages();
766   cursor_client.HideCursor();
767   EXPECT_EQ(0u, sink_->message_count());
768
769   // Showing the cursor should send a message.
770   sink_->ClearMessages();
771   cursor_client.ShowCursor();
772   EXPECT_EQ(1u, sink_->message_count());
773   EXPECT_TRUE(sink_->GetUniqueMessageMatching(
774       InputMsg_CursorVisibilityChange::ID));
775
776   // No messages should be sent while the view is invisible.
777   view_->WasHidden();
778   sink_->ClearMessages();
779   cursor_client.HideCursor();
780   EXPECT_EQ(0u, sink_->message_count());
781
782   // Show the view. Since the cursor was visible when the view was hidden,
783   // a message is expected to be sent.
784   sink_->ClearMessages();
785   view_->WasShown();
786   EXPECT_TRUE(sink_->GetUniqueMessageMatching(
787       InputMsg_CursorVisibilityChange::ID));
788
789   cursor_client.RemoveObserver(view_);
790 }
791
792 TEST_F(RenderWidgetHostViewAuraTest, UpdateCursorIfOverSelf) {
793   view_->InitAsChild(NULL);
794   aura::client::ParentWindowWithContext(
795       view_->GetNativeView(),
796       parent_view_->GetNativeView()->GetRootWindow(),
797       gfx::Rect());
798
799   // Note that all coordinates in this test are screen coordinates.
800   view_->SetBounds(gfx::Rect(60, 60, 100, 100));
801   view_->Show();
802
803   aura::test::TestCursorClient cursor_client(
804       parent_view_->GetNativeView()->GetRootWindow());
805
806   // Cursor is in the middle of the window.
807   cursor_client.reset_calls_to_set_cursor();
808   aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(110, 110));
809   view_->UpdateCursorIfOverSelf();
810   EXPECT_EQ(1, cursor_client.calls_to_set_cursor());
811
812   // Cursor is near the top of the window.
813   cursor_client.reset_calls_to_set_cursor();
814   aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(80, 65));
815   view_->UpdateCursorIfOverSelf();
816   EXPECT_EQ(1, cursor_client.calls_to_set_cursor());
817
818   // Cursor is near the bottom of the window.
819   cursor_client.reset_calls_to_set_cursor();
820   aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(159, 159));
821   view_->UpdateCursorIfOverSelf();
822   EXPECT_EQ(1, cursor_client.calls_to_set_cursor());
823
824   // Cursor is above the window.
825   cursor_client.reset_calls_to_set_cursor();
826   aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(67, 59));
827   view_->UpdateCursorIfOverSelf();
828   EXPECT_EQ(0, cursor_client.calls_to_set_cursor());
829
830   // Cursor is below the window.
831   cursor_client.reset_calls_to_set_cursor();
832   aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(161, 161));
833   view_->UpdateCursorIfOverSelf();
834   EXPECT_EQ(0, cursor_client.calls_to_set_cursor());
835 }
836
837 scoped_ptr<cc::CompositorFrame> MakeGLFrame(float scale_factor,
838                                             gfx::Size size,
839                                             gfx::Rect damage) {
840   scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
841   frame->metadata.device_scale_factor = scale_factor;
842   frame->gl_frame_data.reset(new cc::GLFrameData);
843   frame->gl_frame_data->sync_point = 1;
844   memset(frame->gl_frame_data->mailbox.name,
845          '1',
846          sizeof(frame->gl_frame_data->mailbox.name));
847   frame->gl_frame_data->size = size;
848   frame->gl_frame_data->sub_buffer_rect = damage;
849   return frame.Pass();
850 }
851
852 scoped_ptr<cc::CompositorFrame> MakeSoftwareFrame(float scale_factor,
853                                                   gfx::Size size,
854                                                   gfx::Rect damage) {
855   scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
856   frame->metadata.device_scale_factor = scale_factor;
857   frame->software_frame_data.reset(new cc::SoftwareFrameData);
858   frame->software_frame_data->id = 1;
859   frame->software_frame_data->size = size;
860   frame->software_frame_data->damage_rect = damage;
861   base::SharedMemory shm;
862   shm.CreateAndMapAnonymous(size.GetArea() * 4);
863   shm.GiveToProcess(base::GetCurrentProcessHandle(),
864                     &frame->software_frame_data->handle);
865   return frame.Pass();
866 }
867
868 scoped_ptr<cc::CompositorFrame> MakeDelegatedFrame(float scale_factor,
869                                                    gfx::Size size,
870                                                    gfx::Rect damage) {
871   scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
872   frame->metadata.device_scale_factor = scale_factor;
873   frame->delegated_frame_data.reset(new cc::DelegatedFrameData);
874
875   scoped_ptr<cc::RenderPass> pass = cc::RenderPass::Create();
876   pass->SetNew(cc::RenderPass::Id(1, 1),
877                gfx::Rect(size),
878                gfx::RectF(damage),
879                gfx::Transform());
880   frame->delegated_frame_data->render_pass_list.push_back(pass.Pass());
881   return frame.Pass();
882 }
883
884 // Resizing in fullscreen mode should send the up-to-date screen info.
885 TEST_F(RenderWidgetHostViewAuraTest, FullscreenResize) {
886   aura::Window* root_window = aura_test_helper_->root_window();
887   root_window->SetLayoutManager(new FullscreenLayoutManager(root_window));
888   view_->InitAsFullscreen(parent_view_);
889   view_->WasShown();
890   widget_host_->ResetSizeAndRepaintPendingFlags();
891   sink_->ClearMessages();
892
893   // Call WasResized to flush the old screen info.
894   view_->GetRenderWidgetHost()->WasResized();
895   {
896     // 0 is CreatingNew message.
897     const IPC::Message* msg = sink_->GetMessageAt(0);
898     EXPECT_EQ(ViewMsg_Resize::ID, msg->type());
899     ViewMsg_Resize::Param params;
900     ViewMsg_Resize::Read(msg, &params);
901     EXPECT_EQ("0,0 800x600",
902               gfx::Rect(params.a.screen_info.availableRect).ToString());
903     EXPECT_EQ("800x600", params.a.new_size.ToString());
904     // Resizes are blocked until we swapped a frame of the correct size, and
905     // we've committed it.
906     view_->OnSwapCompositorFrame(
907         0, MakeGLFrame(1.f, params.a.new_size, gfx::Rect(params.a.new_size)));
908     ui::DrawWaiterForTest::WaitForCommit(
909         root_window->GetDispatcher()->host()->compositor());
910   }
911
912   widget_host_->ResetSizeAndRepaintPendingFlags();
913   sink_->ClearMessages();
914
915   // Make sure the corrent screen size is set along in the resize
916   // request when the screen size has changed.
917   aura_test_helper_->test_screen()->SetUIScale(0.5);
918   EXPECT_EQ(1u, sink_->message_count());
919   {
920     const IPC::Message* msg = sink_->GetMessageAt(0);
921     EXPECT_EQ(ViewMsg_Resize::ID, msg->type());
922     ViewMsg_Resize::Param params;
923     ViewMsg_Resize::Read(msg, &params);
924     EXPECT_EQ("0,0 1600x1200",
925               gfx::Rect(params.a.screen_info.availableRect).ToString());
926     EXPECT_EQ("1600x1200", params.a.new_size.ToString());
927     view_->OnSwapCompositorFrame(
928         0, MakeGLFrame(1.f, params.a.new_size, gfx::Rect(params.a.new_size)));
929     ui::DrawWaiterForTest::WaitForCommit(
930         root_window->GetDispatcher()->host()->compositor());
931   }
932 }
933
934 // Swapping a frame should notify the window.
935 TEST_F(RenderWidgetHostViewAuraTest, SwapNotifiesWindow) {
936   gfx::Size view_size(100, 100);
937   gfx::Rect view_rect(view_size);
938
939   view_->InitAsChild(NULL);
940   aura::client::ParentWindowWithContext(
941       view_->GetNativeView(),
942       parent_view_->GetNativeView()->GetRootWindow(),
943       gfx::Rect());
944   view_->SetSize(view_size);
945   view_->WasShown();
946
947   MockWindowObserver observer;
948   view_->window_->AddObserver(&observer);
949
950   // Swap a frame through the GPU path.
951   GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
952   params.surface_id = widget_host_->surface_id();
953   params.route_id = widget_host_->GetRoutingID();
954   memset(params.mailbox.name, '1', sizeof(params.mailbox.name));
955   params.size = view_size;
956   params.scale_factor = 1.f;
957
958   EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
959   view_->AcceleratedSurfaceBuffersSwapped(params, 0);
960   testing::Mock::VerifyAndClearExpectations(&observer);
961
962   // DSF = 2
963   params.size = gfx::Size(200, 200);
964   params.scale_factor = 2.f;
965   EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
966   view_->AcceleratedSurfaceBuffersSwapped(params, 0);
967   testing::Mock::VerifyAndClearExpectations(&observer);
968
969   // Partial frames though GPU path
970   GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params post_params;
971   post_params.surface_id = widget_host_->surface_id();
972   post_params.route_id = widget_host_->GetRoutingID();
973   memset(post_params.mailbox.name, '1', sizeof(post_params.mailbox.name));
974   post_params.surface_size = gfx::Size(200, 200);
975   post_params.surface_scale_factor = 2.f;
976   post_params.x = 40;
977   post_params.y = 40;
978   post_params.width = 80;
979   post_params.height = 80;
980   // rect from params is upside down, and is inflated in RWHVA, just because.
981   EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_,
982                                                gfx::Rect(19, 39, 42, 42)));
983   view_->AcceleratedSurfacePostSubBuffer(post_params, 0);
984   testing::Mock::VerifyAndClearExpectations(&observer);
985
986   // Composite-to-mailbox path
987   EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
988   view_->OnSwapCompositorFrame(0, MakeGLFrame(1.f, view_size, view_rect));
989   testing::Mock::VerifyAndClearExpectations(&observer);
990
991   // rect from GL frame is upside down, and is inflated in RWHVA, just because.
992   EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_,
993                                                gfx::Rect(4, 89, 7, 7)));
994   view_->OnSwapCompositorFrame(
995       0, MakeGLFrame(1.f, view_size, gfx::Rect(5, 5, 5, 5)));
996   testing::Mock::VerifyAndClearExpectations(&observer);
997
998   // Software path
999   EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
1000   view_->OnSwapCompositorFrame(0, MakeSoftwareFrame(1.f, view_size, view_rect));
1001   testing::Mock::VerifyAndClearExpectations(&observer);
1002
1003   EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_,
1004                                                gfx::Rect(5, 5, 5, 5)));
1005   view_->OnSwapCompositorFrame(
1006       0, MakeSoftwareFrame(1.f, view_size, gfx::Rect(5, 5, 5, 5)));
1007   testing::Mock::VerifyAndClearExpectations(&observer);
1008
1009   // Delegated renderer path
1010   EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
1011   view_->OnSwapCompositorFrame(
1012       0, MakeDelegatedFrame(1.f, view_size, view_rect));
1013   testing::Mock::VerifyAndClearExpectations(&observer);
1014
1015   EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_,
1016                                                gfx::Rect(5, 5, 5, 5)));
1017   view_->OnSwapCompositorFrame(
1018       0, MakeDelegatedFrame(1.f, view_size, gfx::Rect(5, 5, 5, 5)));
1019   testing::Mock::VerifyAndClearExpectations(&observer);
1020
1021   view_->window_->RemoveObserver(&observer);
1022 }
1023
1024 // Skipped frames should not drop their damage.
1025 TEST_F(RenderWidgetHostViewAuraTest, SkippedDelegatedFrames) {
1026   gfx::Rect view_rect(100, 100);
1027   gfx::Size frame_size = view_rect.size();
1028
1029   view_->InitAsChild(NULL);
1030   aura::client::ParentWindowWithContext(
1031       view_->GetNativeView(),
1032       parent_view_->GetNativeView()->GetRootWindow(),
1033       gfx::Rect());
1034   view_->SetSize(view_rect.size());
1035
1036   MockWindowObserver observer;
1037   view_->window_->AddObserver(&observer);
1038
1039   // A full frame of damage.
1040   EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
1041   view_->OnSwapCompositorFrame(
1042       0, MakeDelegatedFrame(1.f, frame_size, view_rect));
1043   testing::Mock::VerifyAndClearExpectations(&observer);
1044   view_->RunOnCompositingDidCommit();
1045
1046   // A partial damage frame.
1047   gfx::Rect partial_view_rect(30, 30, 20, 20);
1048   EXPECT_CALL(observer,
1049               OnWindowPaintScheduled(view_->window_, partial_view_rect));
1050   view_->OnSwapCompositorFrame(
1051       0, MakeDelegatedFrame(1.f, frame_size, partial_view_rect));
1052   testing::Mock::VerifyAndClearExpectations(&observer);
1053   view_->RunOnCompositingDidCommit();
1054
1055   // Lock the compositor. Now we should drop frames.
1056   view_rect = gfx::Rect(150, 150);
1057   view_->SetSize(view_rect.size());
1058   view_->MaybeCreateResizeLock();
1059
1060   // This frame is dropped.
1061   gfx::Rect dropped_damage_rect_1(10, 20, 30, 40);
1062   EXPECT_CALL(observer, OnWindowPaintScheduled(_, _)).Times(0);
1063   view_->OnSwapCompositorFrame(
1064       0, MakeDelegatedFrame(1.f, frame_size, dropped_damage_rect_1));
1065   testing::Mock::VerifyAndClearExpectations(&observer);
1066   view_->RunOnCompositingDidCommit();
1067
1068   gfx::Rect dropped_damage_rect_2(40, 50, 10, 20);
1069   EXPECT_CALL(observer, OnWindowPaintScheduled(_, _)).Times(0);
1070   view_->OnSwapCompositorFrame(
1071       0, MakeDelegatedFrame(1.f, frame_size, dropped_damage_rect_2));
1072   testing::Mock::VerifyAndClearExpectations(&observer);
1073   view_->RunOnCompositingDidCommit();
1074
1075   // Unlock the compositor. This frame should damage everything.
1076   frame_size = view_rect.size();
1077
1078   gfx::Rect new_damage_rect(5, 6, 10, 10);
1079   EXPECT_CALL(observer,
1080               OnWindowPaintScheduled(view_->window_, view_rect));
1081   view_->OnSwapCompositorFrame(
1082       0, MakeDelegatedFrame(1.f, frame_size, new_damage_rect));
1083   testing::Mock::VerifyAndClearExpectations(&observer);
1084   view_->RunOnCompositingDidCommit();
1085
1086   // A partial damage frame, this should not be dropped.
1087   EXPECT_CALL(observer,
1088               OnWindowPaintScheduled(view_->window_, partial_view_rect));
1089   view_->OnSwapCompositorFrame(
1090       0, MakeDelegatedFrame(1.f, frame_size, partial_view_rect));
1091   testing::Mock::VerifyAndClearExpectations(&observer);
1092   view_->RunOnCompositingDidCommit();
1093
1094
1095   view_->window_->RemoveObserver(&observer);
1096 }
1097
1098 TEST_F(RenderWidgetHostViewAuraTest, OutputSurfaceIdChange) {
1099   gfx::Rect view_rect(100, 100);
1100   gfx::Size frame_size = view_rect.size();
1101
1102   view_->InitAsChild(NULL);
1103   aura::client::ParentWindowWithContext(
1104       view_->GetNativeView(),
1105       parent_view_->GetNativeView()->GetRootWindow(),
1106       gfx::Rect());
1107   view_->SetSize(view_rect.size());
1108
1109   MockWindowObserver observer;
1110   view_->window_->AddObserver(&observer);
1111
1112   // Swap a frame.
1113   EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
1114   view_->OnSwapCompositorFrame(
1115       0, MakeDelegatedFrame(1.f, frame_size, view_rect));
1116   testing::Mock::VerifyAndClearExpectations(&observer);
1117   view_->RunOnCompositingDidCommit();
1118
1119   // Swap a frame with a different surface id.
1120   EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
1121   view_->OnSwapCompositorFrame(
1122       1, MakeDelegatedFrame(1.f, frame_size, view_rect));
1123   testing::Mock::VerifyAndClearExpectations(&observer);
1124   view_->RunOnCompositingDidCommit();
1125
1126   // Swap an empty frame, with a different surface id.
1127   view_->OnSwapCompositorFrame(
1128       2, MakeDelegatedFrame(1.f, gfx::Size(), gfx::Rect()));
1129   testing::Mock::VerifyAndClearExpectations(&observer);
1130   view_->RunOnCompositingDidCommit();
1131
1132   // Swap another frame, with a different surface id.
1133   EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
1134   view_->OnSwapCompositorFrame(3,
1135                                MakeDelegatedFrame(1.f, frame_size, view_rect));
1136   testing::Mock::VerifyAndClearExpectations(&observer);
1137   view_->RunOnCompositingDidCommit();
1138
1139   view_->window_->RemoveObserver(&observer);
1140 }
1141
1142 TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFrames) {
1143   size_t max_renderer_frames =
1144       RendererFrameManager::GetInstance()->max_number_of_saved_frames();
1145   ASSERT_LE(2u, max_renderer_frames);
1146   size_t renderer_count = max_renderer_frames + 1;
1147   gfx::Rect view_rect(100, 100);
1148   gfx::Size frame_size = view_rect.size();
1149
1150   scoped_ptr<RenderWidgetHostImpl * []> hosts(
1151       new RenderWidgetHostImpl* [renderer_count]);
1152   scoped_ptr<FakeRenderWidgetHostViewAura * []> views(
1153       new FakeRenderWidgetHostViewAura* [renderer_count]);
1154
1155   // Create a bunch of renderers.
1156   for (size_t i = 0; i < renderer_count; ++i) {
1157     hosts[i] = new RenderWidgetHostImpl(
1158         &delegate_, process_host_, MSG_ROUTING_NONE, false);
1159     hosts[i]->Init();
1160     hosts[i]->OnMessageReceived(
1161         ViewHostMsg_DidActivateAcceleratedCompositing(0, true));
1162     views[i] = new FakeRenderWidgetHostViewAura(hosts[i]);
1163     views[i]->InitAsChild(NULL);
1164     aura::client::ParentWindowWithContext(
1165         views[i]->GetNativeView(),
1166         parent_view_->GetNativeView()->GetRootWindow(),
1167         gfx::Rect());
1168     views[i]->SetSize(view_rect.size());
1169   }
1170
1171   // Make each renderer visible, and swap a frame on it, then make it invisible.
1172   for (size_t i = 0; i < renderer_count; ++i) {
1173     views[i]->WasShown();
1174     views[i]->OnSwapCompositorFrame(
1175         1, MakeDelegatedFrame(1.f, frame_size, view_rect));
1176     EXPECT_TRUE(views[i]->frame_provider_);
1177     views[i]->WasHidden();
1178   }
1179
1180   // There should be max_renderer_frames with a frame in it, and one without it.
1181   // Since the logic is LRU eviction, the first one should be without.
1182   EXPECT_FALSE(views[0]->frame_provider_);
1183   for (size_t i = 1; i < renderer_count; ++i)
1184     EXPECT_TRUE(views[i]->frame_provider_);
1185
1186   // LRU renderer is [0], make it visible, it shouldn't evict anything yet.
1187   views[0]->WasShown();
1188   EXPECT_FALSE(views[0]->frame_provider_);
1189   EXPECT_TRUE(views[1]->frame_provider_);
1190
1191   // Swap a frame on it, it should evict the next LRU [1].
1192   views[0]->OnSwapCompositorFrame(
1193       1, MakeDelegatedFrame(1.f, frame_size, view_rect));
1194   EXPECT_TRUE(views[0]->frame_provider_);
1195   EXPECT_FALSE(views[1]->frame_provider_);
1196   views[0]->WasHidden();
1197
1198   // LRU renderer is [1], still hidden. Swap a frame on it, it should evict
1199   // the next LRU [2].
1200   views[1]->OnSwapCompositorFrame(
1201       1, MakeDelegatedFrame(1.f, frame_size, view_rect));
1202   EXPECT_TRUE(views[0]->frame_provider_);
1203   EXPECT_TRUE(views[1]->frame_provider_);
1204   EXPECT_FALSE(views[2]->frame_provider_);
1205   for (size_t i = 3; i < renderer_count; ++i)
1206     EXPECT_TRUE(views[i]->frame_provider_);
1207
1208   // Make all renderers but [0] visible and swap a frame on them, keep [0]
1209   // hidden, it becomes the LRU.
1210   for (size_t i = 1; i < renderer_count; ++i) {
1211     views[i]->WasShown();
1212     views[i]->OnSwapCompositorFrame(
1213         1, MakeDelegatedFrame(1.f, frame_size, view_rect));
1214     EXPECT_TRUE(views[i]->frame_provider_);
1215   }
1216   EXPECT_FALSE(views[0]->frame_provider_);
1217
1218   // Swap a frame on [0], it should be evicted immediately.
1219   views[0]->OnSwapCompositorFrame(
1220       1, MakeDelegatedFrame(1.f, frame_size, view_rect));
1221   EXPECT_FALSE(views[0]->frame_provider_);
1222
1223   // Make [0] visible, and swap a frame on it. Nothing should be evicted
1224   // although we're above the limit.
1225   views[0]->WasShown();
1226   views[0]->OnSwapCompositorFrame(
1227       1, MakeDelegatedFrame(1.f, frame_size, view_rect));
1228   for (size_t i = 0; i < renderer_count; ++i)
1229     EXPECT_TRUE(views[i]->frame_provider_);
1230
1231   // Make [0] hidden, it should evict its frame.
1232   views[0]->WasHidden();
1233   EXPECT_FALSE(views[0]->frame_provider_);
1234
1235   for (size_t i = 0; i < renderer_count; ++i) {
1236     views[i]->Destroy();
1237     delete hosts[i];
1238   }
1239 }
1240
1241 TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithLocking) {
1242   size_t max_renderer_frames =
1243       RendererFrameManager::GetInstance()->max_number_of_saved_frames();
1244   ASSERT_LE(2u, max_renderer_frames);
1245   size_t renderer_count = max_renderer_frames + 1;
1246   gfx::Rect view_rect(100, 100);
1247   gfx::Size frame_size = view_rect.size();
1248
1249   scoped_ptr<RenderWidgetHostImpl * []> hosts(
1250       new RenderWidgetHostImpl* [renderer_count]);
1251   scoped_ptr<FakeRenderWidgetHostViewAura * []> views(
1252       new FakeRenderWidgetHostViewAura* [renderer_count]);
1253
1254   // Create a bunch of renderers.
1255   for (size_t i = 0; i < renderer_count; ++i) {
1256     hosts[i] = new RenderWidgetHostImpl(
1257         &delegate_, process_host_, MSG_ROUTING_NONE, false);
1258     hosts[i]->Init();
1259     hosts[i]->OnMessageReceived(
1260         ViewHostMsg_DidActivateAcceleratedCompositing(0, true));
1261     views[i] = new FakeRenderWidgetHostViewAura(hosts[i]);
1262     views[i]->InitAsChild(NULL);
1263     aura::client::ParentWindowWithContext(
1264         views[i]->GetNativeView(),
1265         parent_view_->GetNativeView()->GetRootWindow(),
1266         gfx::Rect());
1267     views[i]->SetSize(view_rect.size());
1268   }
1269
1270   // Make each renderer visible and swap a frame on it. No eviction should
1271   // occur because all frames are visible.
1272   for (size_t i = 0; i < renderer_count; ++i) {
1273     views[i]->WasShown();
1274     views[i]->OnSwapCompositorFrame(
1275         1, MakeDelegatedFrame(1.f, frame_size, view_rect));
1276     EXPECT_TRUE(views[i]->frame_provider_);
1277   }
1278
1279   // If we hide [0], then [0] should be evicted.
1280   views[0]->WasHidden();
1281   EXPECT_FALSE(views[0]->frame_provider_);
1282
1283   // If we lock [0] before hiding it, then [0] should not be evicted.
1284   views[0]->WasShown();
1285   views[0]->OnSwapCompositorFrame(
1286         1, MakeDelegatedFrame(1.f, frame_size, view_rect));
1287   EXPECT_TRUE(views[0]->frame_provider_);
1288   views[0]->LockResources();
1289   views[0]->WasHidden();
1290   EXPECT_TRUE(views[0]->frame_provider_);
1291
1292   // If we unlock [0] now, then [0] should be evicted.
1293   views[0]->UnlockResources();
1294   EXPECT_FALSE(views[0]->frame_provider_);
1295
1296   for (size_t i = 0; i < renderer_count; ++i) {
1297     views[i]->Destroy();
1298     delete hosts[i];
1299   }
1300 }
1301
1302 TEST_F(RenderWidgetHostViewAuraTest, SoftwareDPIChange) {
1303   gfx::Rect view_rect(100, 100);
1304   gfx::Size frame_size(100, 100);
1305
1306   view_->InitAsChild(NULL);
1307   aura::client::ParentWindowWithContext(
1308       view_->GetNativeView(),
1309       parent_view_->GetNativeView()->GetRootWindow(),
1310       gfx::Rect());
1311   view_->SetSize(view_rect.size());
1312   view_->WasShown();
1313
1314   // With a 1x DPI UI and 1x DPI Renderer.
1315   view_->OnSwapCompositorFrame(
1316       1, MakeDelegatedFrame(1.f, frame_size, gfx::Rect(frame_size)));
1317
1318   // Save the frame provider.
1319   scoped_refptr<cc::DelegatedFrameProvider> frame_provider =
1320       view_->frame_provider_;
1321
1322   // This frame will have the same number of physical pixels, but has a new
1323   // scale on it.
1324   view_->OnSwapCompositorFrame(
1325       1, MakeDelegatedFrame(2.f, frame_size, gfx::Rect(frame_size)));
1326
1327   // When we get a new frame with the same frame size in physical pixels, but a
1328   // different scale, we should generate a new frame provider, as the final
1329   // result will need to be scaled differently to the screen.
1330   EXPECT_NE(frame_provider.get(), view_->frame_provider_.get());
1331 }
1332
1333 class RenderWidgetHostViewAuraCopyRequestTest
1334     : public RenderWidgetHostViewAuraShutdownTest {
1335  public:
1336   RenderWidgetHostViewAuraCopyRequestTest()
1337       : callback_count_(0), result_(false) {}
1338
1339   void CallbackMethod(bool result) {
1340     result_ = result;
1341     callback_count_++;
1342   }
1343
1344   int callback_count_;
1345   bool result_;
1346
1347  private:
1348   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAuraCopyRequestTest);
1349 };
1350
1351 TEST_F(RenderWidgetHostViewAuraCopyRequestTest, DestroyedAfterCopyRequest) {
1352   gfx::Rect view_rect(100, 100);
1353   scoped_ptr<cc::CopyOutputRequest> request;
1354
1355   view_->InitAsChild(NULL);
1356   aura::client::ParentWindowWithContext(
1357       view_->GetNativeView(),
1358       parent_view_->GetNativeView()->GetRootWindow(),
1359       gfx::Rect());
1360   view_->SetSize(view_rect.size());
1361   view_->WasShown();
1362
1363   scoped_ptr<FakeFrameSubscriber> frame_subscriber(new FakeFrameSubscriber(
1364       view_rect.size(),
1365       base::Bind(&RenderWidgetHostViewAuraCopyRequestTest::CallbackMethod,
1366                  base::Unretained(this))));
1367
1368   EXPECT_EQ(0, callback_count_);
1369   EXPECT_FALSE(view_->last_copy_request_);
1370
1371   view_->BeginFrameSubscription(
1372       frame_subscriber.PassAs<RenderWidgetHostViewFrameSubscriber>());
1373   view_->OnSwapCompositorFrame(
1374       1, MakeDelegatedFrame(1.f, view_rect.size(), gfx::Rect(view_rect)));
1375
1376   EXPECT_EQ(0, callback_count_);
1377   EXPECT_TRUE(view_->last_copy_request_);
1378   EXPECT_TRUE(view_->last_copy_request_->has_texture_mailbox());
1379   request = view_->last_copy_request_.Pass();
1380
1381   // There should be one subscriber texture in flight.
1382   EXPECT_EQ(1u, view_->active_frame_subscriber_textures_.size());
1383
1384   // Send back the mailbox included in the request. There's no release callback
1385   // since the mailbox came from the RWHVA originally.
1386   request->SendTextureResult(view_rect.size(),
1387                              request->texture_mailbox(),
1388                              scoped_ptr<cc::SingleReleaseCallback>());
1389
1390   base::RunLoop run_loop;
1391   run_loop.RunUntilIdle();
1392
1393   // The callback should succeed.
1394   EXPECT_EQ(0u, view_->active_frame_subscriber_textures_.size());
1395   EXPECT_EQ(1, callback_count_);
1396   EXPECT_TRUE(result_);
1397
1398   view_->OnSwapCompositorFrame(
1399       1, MakeDelegatedFrame(1.f, view_rect.size(), gfx::Rect(view_rect)));
1400
1401   EXPECT_EQ(1, callback_count_);
1402   request = view_->last_copy_request_.Pass();
1403
1404   // There should be one subscriber texture in flight again.
1405   EXPECT_EQ(1u, view_->active_frame_subscriber_textures_.size());
1406
1407   // Destroy the RenderWidgetHostViewAura and ImageTransportFactory.
1408   TearDownEnvironment();
1409
1410   // Send back the mailbox included in the request. There's no release callback
1411   // since the mailbox came from the RWHVA originally.
1412   request->SendTextureResult(view_rect.size(),
1413                              request->texture_mailbox(),
1414                              scoped_ptr<cc::SingleReleaseCallback>());
1415
1416   // Because the copy request callback may be holding state within it, that
1417   // state must handle the RWHVA and ImageTransportFactory going away before the
1418   // callback is called. This test passes if it does not crash as a result of
1419   // these things being destroyed.
1420   EXPECT_EQ(2, callback_count_);
1421   EXPECT_FALSE(result_);
1422 }
1423
1424 }  // namespace content