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