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.
5 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
7 #include "base/basictypes.h"
8 #include "base/command_line.h"
9 #include "base/memory/shared_memory.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/run_loop.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "cc/output/compositor_frame.h"
14 #include "cc/output/compositor_frame_metadata.h"
15 #include "cc/output/copy_output_request.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/host_shared_bitmap_manager.h"
22 #include "content/common/input_messages.h"
23 #include "content/common/view_messages.h"
24 #include "content/public/browser/render_widget_host_view.h"
25 #include "content/public/browser/render_widget_host_view_frame_subscriber.h"
26 #include "content/public/test/mock_render_process_host.h"
27 #include "content/public/test/test_browser_context.h"
28 #include "ipc/ipc_test_sink.h"
29 #include "testing/gmock/include/gmock/gmock.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31 #include "ui/aura/client/aura_constants.h"
32 #include "ui/aura/client/screen_position_client.h"
33 #include "ui/aura/client/window_tree_client.h"
34 #include "ui/aura/env.h"
35 #include "ui/aura/layout_manager.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_event_dispatcher.h"
43 #include "ui/aura/window_observer.h"
44 #include "ui/base/ui_base_types.h"
45 #include "ui/compositor/compositor.h"
46 #include "ui/compositor/test/draw_waiter_for_test.h"
47 #include "ui/compositor/test/in_process_context_factory.h"
48 #include "ui/events/event.h"
49 #include "ui/events/event_utils.h"
50 #include "ui/wm/core/default_activation_client.h"
57 // Simple screen position client to test coordinate system conversion.
58 class TestScreenPositionClient
59 : public aura::client::ScreenPositionClient
{
61 TestScreenPositionClient() {}
62 virtual ~TestScreenPositionClient() {}
64 // aura::client::ScreenPositionClient overrides:
65 virtual void ConvertPointToScreen(const aura::Window
* window
,
66 gfx::Point
* point
) OVERRIDE
{
67 point
->Offset(-1, -1);
70 virtual void ConvertPointFromScreen(const aura::Window
* window
,
71 gfx::Point
* point
) OVERRIDE
{
75 virtual void ConvertHostPointToScreen(aura::Window
* window
,
76 gfx::Point
* point
) OVERRIDE
{
77 ConvertPointToScreen(window
, point
);
80 virtual void SetBounds(aura::Window
* window
,
81 const gfx::Rect
& bounds
,
82 const gfx::Display
& display
) OVERRIDE
{
86 class MockRenderWidgetHostDelegate
: public RenderWidgetHostDelegate
{
88 MockRenderWidgetHostDelegate() {}
89 virtual ~MockRenderWidgetHostDelegate() {}
92 // Simple observer that keeps track of changes to a window for tests.
93 class TestWindowObserver
: public aura::WindowObserver
{
95 explicit TestWindowObserver(aura::Window
* window_to_observe
)
96 : window_(window_to_observe
) {
97 window_
->AddObserver(this);
99 virtual ~TestWindowObserver() {
101 window_
->RemoveObserver(this);
104 bool destroyed() const { return destroyed_
; }
106 // aura::WindowObserver overrides:
107 virtual void OnWindowDestroyed(aura::Window
* window
) OVERRIDE
{
108 CHECK_EQ(window
, window_
);
114 // Window that we're observing, or NULL if it's been destroyed.
115 aura::Window
* window_
;
117 // Was |window_| destroyed?
120 DISALLOW_COPY_AND_ASSIGN(TestWindowObserver
);
123 class FakeFrameSubscriber
: public RenderWidgetHostViewFrameSubscriber
{
125 FakeFrameSubscriber(gfx::Size size
, base::Callback
<void(bool)> callback
)
126 : size_(size
), callback_(callback
) {}
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
,
136 *callback
= base::Bind(&FakeFrameSubscriber::CallbackMethod
, callback_
);
140 static void CallbackMethod(base::Callback
<void(bool)> callback
,
141 base::TimeTicks timestamp
,
143 callback
.Run(success
);
148 base::Callback
<void(bool)> callback_
;
151 class FakeRenderWidgetHostViewAura
: public RenderWidgetHostViewAura
{
153 FakeRenderWidgetHostViewAura(RenderWidgetHost
* widget
)
154 : RenderWidgetHostViewAura(widget
), has_resize_lock_(false) {}
156 virtual ~FakeRenderWidgetHostViewAura() {}
158 virtual scoped_ptr
<ResizeLock
> CreateResizeLock(
159 bool defer_compositor_lock
) OVERRIDE
{
160 gfx::Size desired_size
= window()->bounds().size();
161 return scoped_ptr
<ResizeLock
>(
162 new FakeResizeLock(desired_size
, defer_compositor_lock
));
165 void RunOnCompositingDidCommit() {
166 GetDelegatedFrameHost()->OnCompositingDidCommitForTesting(
167 window()->GetHost()->compositor());
170 virtual bool ShouldCreateResizeLock() OVERRIDE
{
171 gfx::Size desired_size
= window()->bounds().size();
172 return desired_size
!=
173 GetDelegatedFrameHost()->CurrentFrameSizeInDIPForTesting();
176 virtual void RequestCopyOfOutput(scoped_ptr
<cc::CopyOutputRequest
> request
)
178 last_copy_request_
= request
.Pass();
179 if (last_copy_request_
->has_texture_mailbox()) {
180 // Give the resulting texture a size.
181 GLHelper
* gl_helper
= ImageTransportFactory::GetInstance()->GetGLHelper();
182 GLuint texture
= gl_helper
->ConsumeMailboxToTexture(
183 last_copy_request_
->texture_mailbox().mailbox(),
184 last_copy_request_
->texture_mailbox().sync_point());
185 gl_helper
->ResizeTexture(texture
, window()->bounds().size());
186 gl_helper
->DeleteTexture(texture
);
190 cc::DelegatedFrameProvider
* frame_provider() const {
191 return GetDelegatedFrameHost()->FrameProviderForTesting();
194 // A lock that doesn't actually do anything to the compositor, and does not
196 class FakeResizeLock
: public ResizeLock
{
198 FakeResizeLock(const gfx::Size new_size
, bool defer_compositor_lock
)
199 : ResizeLock(new_size
, defer_compositor_lock
) {}
202 bool has_resize_lock_
;
203 gfx::Size last_frame_size_
;
204 scoped_ptr
<cc::CopyOutputRequest
> last_copy_request_
;
207 class RenderWidgetHostViewAuraTest
: public testing::Test
{
209 RenderWidgetHostViewAuraTest()
210 : browser_thread_for_ui_(BrowserThread::UI
, &message_loop_
) {}
212 void SetUpEnvironment() {
213 ImageTransportFactory::InitializeForUnitTests(
214 scoped_ptr
<ui::ContextFactory
>(new ui::InProcessContextFactory
));
215 aura_test_helper_
.reset(new aura::test::AuraTestHelper(&message_loop_
));
216 aura_test_helper_
->SetUp();
217 new wm::DefaultActivationClient(aura_test_helper_
->root_window());
219 browser_context_
.reset(new TestBrowserContext
);
220 process_host_
= new MockRenderProcessHost(browser_context_
.get());
222 sink_
= &process_host_
->sink();
224 parent_host_
= new RenderWidgetHostImpl(
225 &delegate_
, process_host_
, MSG_ROUTING_NONE
, false);
226 parent_view_
= new RenderWidgetHostViewAura(parent_host_
);
227 parent_view_
->InitAsChild(NULL
);
228 aura::client::ParentWindowWithContext(parent_view_
->GetNativeView(),
229 aura_test_helper_
->root_window(),
232 widget_host_
= new RenderWidgetHostImpl(
233 &delegate_
, process_host_
, MSG_ROUTING_NONE
, false);
234 widget_host_
->Init();
235 widget_host_
->OnMessageReceived(
236 ViewHostMsg_DidActivateAcceleratedCompositing(0, true));
237 view_
= new FakeRenderWidgetHostViewAura(widget_host_
);
240 void TearDownEnvironment() {
242 process_host_
= NULL
;
247 parent_view_
->Destroy();
250 browser_context_
.reset();
251 aura_test_helper_
->TearDown();
253 message_loop_
.DeleteSoon(FROM_HERE
, browser_context_
.release());
254 message_loop_
.RunUntilIdle();
255 ImageTransportFactory::Terminate();
258 virtual void SetUp() { SetUpEnvironment(); }
260 virtual void TearDown() { TearDownEnvironment(); }
263 base::MessageLoopForUI message_loop_
;
264 BrowserThreadImpl browser_thread_for_ui_
;
265 scoped_ptr
<aura::test::AuraTestHelper
> aura_test_helper_
;
266 scoped_ptr
<BrowserContext
> browser_context_
;
267 MockRenderWidgetHostDelegate delegate_
;
268 MockRenderProcessHost
* process_host_
;
270 // Tests should set these to NULL if they've already triggered their
272 RenderWidgetHostImpl
* parent_host_
;
273 RenderWidgetHostViewAura
* parent_view_
;
275 // Tests should set these to NULL if they've already triggered their
277 RenderWidgetHostImpl
* widget_host_
;
278 FakeRenderWidgetHostViewAura
* view_
;
280 IPC::TestSink
* sink_
;
283 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAuraTest
);
286 class RenderWidgetHostViewAuraShutdownTest
287 : public RenderWidgetHostViewAuraTest
{
289 RenderWidgetHostViewAuraShutdownTest() {}
291 virtual void TearDown() OVERRIDE
{
292 // No TearDownEnvironment here, we do this explicitly during the test.
296 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAuraShutdownTest
);
299 // A layout manager that always resizes a child to the root window size.
300 class FullscreenLayoutManager
: public aura::LayoutManager
{
302 explicit FullscreenLayoutManager(aura::Window
* owner
)
304 virtual ~FullscreenLayoutManager() {}
306 // Overridden from aura::LayoutManager:
307 virtual void OnWindowResized() OVERRIDE
{
308 aura::Window::Windows::const_iterator i
;
309 for (i
= owner_
->children().begin(); i
!= owner_
->children().end(); ++i
) {
310 (*i
)->SetBounds(gfx::Rect());
313 virtual void OnWindowAddedToLayout(aura::Window
* child
) OVERRIDE
{
314 child
->SetBounds(gfx::Rect());
316 virtual void OnWillRemoveWindowFromLayout(aura::Window
* child
) OVERRIDE
{
318 virtual void OnWindowRemovedFromLayout(aura::Window
* child
) OVERRIDE
{
320 virtual void OnChildWindowVisibilityChanged(aura::Window
* child
,
321 bool visible
) OVERRIDE
{
323 virtual void SetChildBounds(aura::Window
* child
,
324 const gfx::Rect
& requested_bounds
) OVERRIDE
{
325 SetChildBoundsDirect(child
, gfx::Rect(owner_
->bounds().size()));
329 aura::Window
* owner_
;
330 DISALLOW_COPY_AND_ASSIGN(FullscreenLayoutManager
);
333 class MockWindowObserver
: public aura::WindowObserver
{
335 MOCK_METHOD2(OnWindowPaintScheduled
, void(aura::Window
*, const gfx::Rect
&));
340 // Checks that a fullscreen view has the correct show-state and receives the
342 TEST_F(RenderWidgetHostViewAuraTest
, FocusFullscreen
) {
343 view_
->InitAsFullscreen(parent_view_
);
344 aura::Window
* window
= view_
->GetNativeView();
345 ASSERT_TRUE(window
!= NULL
);
346 EXPECT_EQ(ui::SHOW_STATE_FULLSCREEN
,
347 window
->GetProperty(aura::client::kShowStateKey
));
349 // Check that we requested and received the focus.
350 EXPECT_TRUE(window
->HasFocus());
352 // Check that we'll also say it's okay to activate the window when there's an
353 // ActivationClient defined.
354 EXPECT_TRUE(view_
->ShouldActivate());
357 // Checks that a popup is positioned correctly relative to its parent using
358 // screen coordinates.
359 TEST_F(RenderWidgetHostViewAuraTest
, PositionChildPopup
) {
360 TestScreenPositionClient screen_position_client
;
362 aura::Window
* window
= parent_view_
->GetNativeView();
363 aura::Window
* root
= window
->GetRootWindow();
364 aura::client::SetScreenPositionClient(root
, &screen_position_client
);
366 parent_view_
->SetBounds(gfx::Rect(10, 10, 800, 600));
367 gfx::Rect bounds_in_screen
= parent_view_
->GetViewBounds();
368 int horiz
= bounds_in_screen
.width() / 4;
369 int vert
= bounds_in_screen
.height() / 4;
370 bounds_in_screen
.Inset(horiz
, vert
);
372 // Verify that when the popup is initialized for the first time, it correctly
373 // treats the input bounds as screen coordinates.
374 view_
->InitAsPopup(parent_view_
, bounds_in_screen
);
376 gfx::Rect final_bounds_in_screen
= view_
->GetViewBounds();
377 EXPECT_EQ(final_bounds_in_screen
.ToString(), bounds_in_screen
.ToString());
379 // Verify that directly setting the bounds via SetBounds() treats the input
380 // as screen coordinates.
381 bounds_in_screen
= gfx::Rect(60, 60, 100, 100);
382 view_
->SetBounds(bounds_in_screen
);
383 final_bounds_in_screen
= view_
->GetViewBounds();
384 EXPECT_EQ(final_bounds_in_screen
.ToString(), bounds_in_screen
.ToString());
386 // Verify that setting the size does not alter the origin.
387 gfx::Point original_origin
= window
->bounds().origin();
388 view_
->SetSize(gfx::Size(120, 120));
389 gfx::Point new_origin
= window
->bounds().origin();
390 EXPECT_EQ(original_origin
.ToString(), new_origin
.ToString());
392 aura::client::SetScreenPositionClient(root
, NULL
);
395 // Checks that a fullscreen view is destroyed when it loses the focus.
396 TEST_F(RenderWidgetHostViewAuraTest
, DestroyFullscreenOnBlur
) {
397 view_
->InitAsFullscreen(parent_view_
);
398 aura::Window
* window
= view_
->GetNativeView();
399 ASSERT_TRUE(window
!= NULL
);
400 ASSERT_TRUE(window
->HasFocus());
402 // After we create and focus another window, the RWHVA's window should be
404 TestWindowObserver
observer(window
);
405 aura::test::TestWindowDelegate delegate
;
406 scoped_ptr
<aura::Window
> sibling(new aura::Window(&delegate
));
407 sibling
->Init(aura::WINDOW_LAYER_TEXTURED
);
409 window
->parent()->AddChild(sibling
.get());
411 ASSERT_TRUE(sibling
->HasFocus());
412 ASSERT_TRUE(observer
.destroyed());
418 // Checks that a popup view is destroyed when a user clicks outside of the popup
419 // view and focus does not change. This is the case when the user clicks on the
420 // desktop background on Chrome OS.
421 TEST_F(RenderWidgetHostViewAuraTest
, DestroyPopupClickOutsidePopup
) {
422 parent_view_
->SetBounds(gfx::Rect(10, 10, 400, 400));
423 parent_view_
->Focus();
424 EXPECT_TRUE(parent_view_
->HasFocus());
426 view_
->InitAsPopup(parent_view_
, gfx::Rect(10, 10, 100, 100));
427 aura::Window
* window
= view_
->GetNativeView();
428 ASSERT_TRUE(window
!= NULL
);
430 gfx::Point click_point
;
431 EXPECT_FALSE(window
->GetBoundsInRootWindow().Contains(click_point
));
432 aura::Window
* parent_window
= parent_view_
->GetNativeView();
433 EXPECT_FALSE(parent_window
->GetBoundsInRootWindow().Contains(click_point
));
435 TestWindowObserver
observer(window
);
436 aura::test::EventGenerator
generator(window
->GetRootWindow(), click_point
);
437 generator
.ClickLeftButton();
438 ASSERT_TRUE(parent_view_
->HasFocus());
439 ASSERT_TRUE(observer
.destroyed());
445 // Checks that a popup view is destroyed when a user taps outside of the popup
446 // view and focus does not change. This is the case when the user taps the
447 // desktop background on Chrome OS.
448 TEST_F(RenderWidgetHostViewAuraTest
, DestroyPopupTapOutsidePopup
) {
449 parent_view_
->SetBounds(gfx::Rect(10, 10, 400, 400));
450 parent_view_
->Focus();
451 EXPECT_TRUE(parent_view_
->HasFocus());
453 view_
->InitAsPopup(parent_view_
, gfx::Rect(10, 10, 100, 100));
454 aura::Window
* window
= view_
->GetNativeView();
455 ASSERT_TRUE(window
!= NULL
);
457 gfx::Point tap_point
;
458 EXPECT_FALSE(window
->GetBoundsInRootWindow().Contains(tap_point
));
459 aura::Window
* parent_window
= parent_view_
->GetNativeView();
460 EXPECT_FALSE(parent_window
->GetBoundsInRootWindow().Contains(tap_point
));
462 TestWindowObserver
observer(window
);
463 aura::test::EventGenerator
generator(window
->GetRootWindow(), tap_point
);
464 generator
.GestureTapAt(tap_point
);
465 ASSERT_TRUE(parent_view_
->HasFocus());
466 ASSERT_TRUE(observer
.destroyed());
472 // Checks that IME-composition-event state is maintained correctly.
473 TEST_F(RenderWidgetHostViewAuraTest
, SetCompositionText
) {
474 view_
->InitAsChild(NULL
);
477 ui::CompositionText composition_text
;
478 composition_text
.text
= base::ASCIIToUTF16("|a|b");
481 composition_text
.underlines
.push_back(
482 ui::CompositionUnderline(0, 3, 0xff000000, true));
484 // Non-focused segment
485 composition_text
.underlines
.push_back(
486 ui::CompositionUnderline(3, 4, 0xff000000, false));
488 const ui::CompositionUnderlines
& underlines
= composition_text
.underlines
;
490 // Caret is at the end. (This emulates Japanese MSIME 2007 and later)
491 composition_text
.selection
= gfx::Range(4);
493 sink_
->ClearMessages();
494 view_
->SetCompositionText(composition_text
);
495 EXPECT_TRUE(view_
->has_composition_text_
);
497 const IPC::Message
* msg
=
498 sink_
->GetFirstMessageMatching(ViewMsg_ImeSetComposition::ID
);
499 ASSERT_TRUE(msg
!= NULL
);
501 ViewMsg_ImeSetComposition::Param params
;
502 ViewMsg_ImeSetComposition::Read(msg
, ¶ms
);
504 EXPECT_EQ(composition_text
.text
, params
.a
);
506 ASSERT_EQ(underlines
.size(), params
.b
.size());
507 for (size_t i
= 0; i
< underlines
.size(); ++i
) {
508 EXPECT_EQ(underlines
[i
].start_offset
, params
.b
[i
].startOffset
);
509 EXPECT_EQ(underlines
[i
].end_offset
, params
.b
[i
].endOffset
);
510 EXPECT_EQ(underlines
[i
].color
, params
.b
[i
].color
);
511 EXPECT_EQ(underlines
[i
].thick
, params
.b
[i
].thick
);
514 EXPECT_EQ(4, params
.c
) << "Should be the same to the caret pos";
515 EXPECT_EQ(4, params
.d
) << "Should be the same to the caret pos";
518 view_
->ImeCancelComposition();
519 EXPECT_FALSE(view_
->has_composition_text_
);
522 // Checks that touch-event state is maintained correctly.
523 TEST_F(RenderWidgetHostViewAuraTest
, TouchEventState
) {
524 view_
->InitAsChild(NULL
);
527 // Start with no touch-event handler in the renderer.
528 widget_host_
->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false));
529 EXPECT_FALSE(widget_host_
->ShouldForwardTouchEvent());
531 ui::TouchEvent
press(ui::ET_TOUCH_PRESSED
,
534 ui::EventTimeForNow());
535 ui::TouchEvent
move(ui::ET_TOUCH_MOVED
,
538 ui::EventTimeForNow());
539 ui::TouchEvent
release(ui::ET_TOUCH_RELEASED
,
542 ui::EventTimeForNow());
544 view_
->OnTouchEvent(&press
);
545 EXPECT_FALSE(press
.handled());
546 EXPECT_EQ(blink::WebInputEvent::TouchStart
, view_
->touch_event_
.type
);
547 EXPECT_TRUE(view_
->touch_event_
.cancelable
);
548 EXPECT_EQ(1U, view_
->touch_event_
.touchesLength
);
549 EXPECT_EQ(blink::WebTouchPoint::StatePressed
,
550 view_
->touch_event_
.touches
[0].state
);
552 view_
->OnTouchEvent(&move
);
553 EXPECT_FALSE(move
.handled());
554 EXPECT_EQ(blink::WebInputEvent::TouchMove
, view_
->touch_event_
.type
);
555 EXPECT_TRUE(view_
->touch_event_
.cancelable
);
556 EXPECT_EQ(1U, view_
->touch_event_
.touchesLength
);
557 EXPECT_EQ(blink::WebTouchPoint::StateMoved
,
558 view_
->touch_event_
.touches
[0].state
);
560 view_
->OnTouchEvent(&release
);
561 EXPECT_FALSE(release
.handled());
562 EXPECT_EQ(blink::WebInputEvent::TouchEnd
, view_
->touch_event_
.type
);
563 EXPECT_TRUE(view_
->touch_event_
.cancelable
);
564 EXPECT_EQ(0U, view_
->touch_event_
.touchesLength
);
566 // Now install some touch-event handlers and do the same steps. The touch
567 // events should now be consumed. However, the touch-event state should be
568 // updated as before.
569 widget_host_
->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true));
570 EXPECT_TRUE(widget_host_
->ShouldForwardTouchEvent());
572 view_
->OnTouchEvent(&press
);
573 EXPECT_TRUE(press
.stopped_propagation());
574 EXPECT_EQ(blink::WebInputEvent::TouchStart
, view_
->touch_event_
.type
);
575 EXPECT_TRUE(view_
->touch_event_
.cancelable
);
576 EXPECT_EQ(1U, view_
->touch_event_
.touchesLength
);
577 EXPECT_EQ(blink::WebTouchPoint::StatePressed
,
578 view_
->touch_event_
.touches
[0].state
);
580 view_
->OnTouchEvent(&move
);
581 EXPECT_TRUE(move
.stopped_propagation());
582 EXPECT_EQ(blink::WebInputEvent::TouchMove
, view_
->touch_event_
.type
);
583 EXPECT_TRUE(view_
->touch_event_
.cancelable
);
584 EXPECT_EQ(1U, view_
->touch_event_
.touchesLength
);
585 EXPECT_EQ(blink::WebTouchPoint::StateMoved
,
586 view_
->touch_event_
.touches
[0].state
);
588 view_
->OnTouchEvent(&release
);
589 EXPECT_TRUE(release
.stopped_propagation());
590 EXPECT_EQ(blink::WebInputEvent::TouchEnd
, view_
->touch_event_
.type
);
591 EXPECT_TRUE(view_
->touch_event_
.cancelable
);
592 EXPECT_EQ(0U, view_
->touch_event_
.touchesLength
);
594 // Now start a touch event, and remove the event-handlers before the release.
595 view_
->OnTouchEvent(&press
);
596 EXPECT_TRUE(press
.stopped_propagation());
597 EXPECT_EQ(blink::WebInputEvent::TouchStart
, view_
->touch_event_
.type
);
598 EXPECT_EQ(1U, view_
->touch_event_
.touchesLength
);
599 EXPECT_EQ(blink::WebTouchPoint::StatePressed
,
600 view_
->touch_event_
.touches
[0].state
);
602 widget_host_
->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false));
603 EXPECT_FALSE(widget_host_
->ShouldForwardTouchEvent());
605 ui::TouchEvent
move2(ui::ET_TOUCH_MOVED
, gfx::Point(20, 20), 0,
606 base::Time::NowFromSystemTime() - base::Time());
607 view_
->OnTouchEvent(&move2
);
608 EXPECT_FALSE(move2
.handled());
609 EXPECT_EQ(blink::WebInputEvent::TouchMove
, view_
->touch_event_
.type
);
610 EXPECT_EQ(1U, view_
->touch_event_
.touchesLength
);
611 EXPECT_EQ(blink::WebTouchPoint::StateMoved
,
612 view_
->touch_event_
.touches
[0].state
);
614 ui::TouchEvent
release2(ui::ET_TOUCH_RELEASED
, gfx::Point(20, 20), 0,
615 base::Time::NowFromSystemTime() - base::Time());
616 view_
->OnTouchEvent(&release2
);
617 EXPECT_FALSE(release2
.handled());
618 EXPECT_EQ(blink::WebInputEvent::TouchEnd
, view_
->touch_event_
.type
);
619 EXPECT_EQ(0U, view_
->touch_event_
.touchesLength
);
622 // Checks that touch-events are queued properly when there is a touch-event
623 // handler on the page.
624 TEST_F(RenderWidgetHostViewAuraTest
, TouchEventSyncAsync
) {
625 view_
->InitAsChild(NULL
);
628 widget_host_
->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true));
629 EXPECT_TRUE(widget_host_
->ShouldForwardTouchEvent());
631 ui::TouchEvent
press(ui::ET_TOUCH_PRESSED
,
634 ui::EventTimeForNow());
635 ui::TouchEvent
move(ui::ET_TOUCH_MOVED
,
638 ui::EventTimeForNow());
639 ui::TouchEvent
release(ui::ET_TOUCH_RELEASED
,
642 ui::EventTimeForNow());
644 view_
->OnTouchEvent(&press
);
645 EXPECT_TRUE(press
.stopped_propagation());
646 EXPECT_EQ(blink::WebInputEvent::TouchStart
, view_
->touch_event_
.type
);
647 EXPECT_EQ(1U, view_
->touch_event_
.touchesLength
);
648 EXPECT_EQ(blink::WebTouchPoint::StatePressed
,
649 view_
->touch_event_
.touches
[0].state
);
651 view_
->OnTouchEvent(&move
);
652 EXPECT_TRUE(move
.stopped_propagation());
653 EXPECT_EQ(blink::WebInputEvent::TouchMove
, view_
->touch_event_
.type
);
654 EXPECT_EQ(1U, view_
->touch_event_
.touchesLength
);
655 EXPECT_EQ(blink::WebTouchPoint::StateMoved
,
656 view_
->touch_event_
.touches
[0].state
);
658 // Send the same move event. Since the point hasn't moved, it won't affect the
659 // queue. However, the view should consume the event.
660 view_
->OnTouchEvent(&move
);
661 EXPECT_TRUE(move
.stopped_propagation());
662 EXPECT_EQ(blink::WebInputEvent::TouchMove
, view_
->touch_event_
.type
);
663 EXPECT_EQ(1U, view_
->touch_event_
.touchesLength
);
664 EXPECT_EQ(blink::WebTouchPoint::StateMoved
,
665 view_
->touch_event_
.touches
[0].state
);
667 view_
->OnTouchEvent(&release
);
668 EXPECT_TRUE(release
.stopped_propagation());
669 EXPECT_EQ(blink::WebInputEvent::TouchEnd
, view_
->touch_event_
.type
);
670 EXPECT_EQ(0U, view_
->touch_event_
.touchesLength
);
673 TEST_F(RenderWidgetHostViewAuraTest
, PhysicalBackingSizeWithScale
) {
674 view_
->InitAsChild(NULL
);
675 aura::client::ParentWindowWithContext(
676 view_
->GetNativeView(),
677 parent_view_
->GetNativeView()->GetRootWindow(),
679 sink_
->ClearMessages();
680 view_
->SetSize(gfx::Size(100, 100));
681 EXPECT_EQ("100x100", view_
->GetPhysicalBackingSize().ToString());
682 EXPECT_EQ(1u, sink_
->message_count());
683 EXPECT_EQ(ViewMsg_Resize::ID
, sink_
->GetMessageAt(0)->type());
685 const IPC::Message
* msg
= sink_
->GetMessageAt(0);
686 EXPECT_EQ(ViewMsg_Resize::ID
, msg
->type());
687 ViewMsg_Resize::Param params
;
688 ViewMsg_Resize::Read(msg
, ¶ms
);
689 EXPECT_EQ("100x100", params
.a
.new_size
.ToString()); // dip size
691 params
.a
.physical_backing_size
.ToString()); // backing size
694 widget_host_
->ResetSizeAndRepaintPendingFlags();
695 sink_
->ClearMessages();
697 aura_test_helper_
->test_screen()->SetDeviceScaleFactor(2.0f
);
698 EXPECT_EQ("200x200", view_
->GetPhysicalBackingSize().ToString());
699 // Extra ScreenInfoChanged message for |parent_view_|.
700 EXPECT_EQ(1u, sink_
->message_count());
702 const IPC::Message
* msg
= sink_
->GetMessageAt(0);
703 EXPECT_EQ(ViewMsg_Resize::ID
, msg
->type());
704 ViewMsg_Resize::Param params
;
705 ViewMsg_Resize::Read(msg
, ¶ms
);
706 EXPECT_EQ(2.0f
, params
.a
.screen_info
.deviceScaleFactor
);
707 EXPECT_EQ("100x100", params
.a
.new_size
.ToString()); // dip size
709 params
.a
.physical_backing_size
.ToString()); // backing size
712 widget_host_
->ResetSizeAndRepaintPendingFlags();
713 sink_
->ClearMessages();
715 aura_test_helper_
->test_screen()->SetDeviceScaleFactor(1.0f
);
716 // Extra ScreenInfoChanged message for |parent_view_|.
717 EXPECT_EQ(1u, sink_
->message_count());
718 EXPECT_EQ("100x100", view_
->GetPhysicalBackingSize().ToString());
720 const IPC::Message
* msg
= sink_
->GetMessageAt(0);
721 EXPECT_EQ(ViewMsg_Resize::ID
, msg
->type());
722 ViewMsg_Resize::Param params
;
723 ViewMsg_Resize::Read(msg
, ¶ms
);
724 EXPECT_EQ(1.0f
, params
.a
.screen_info
.deviceScaleFactor
);
725 EXPECT_EQ("100x100", params
.a
.new_size
.ToString()); // dip size
727 params
.a
.physical_backing_size
.ToString()); // backing size
731 // Checks that InputMsg_CursorVisibilityChange IPC messages are dispatched
732 // to the renderer at the correct times.
733 TEST_F(RenderWidgetHostViewAuraTest
, CursorVisibilityChange
) {
734 view_
->InitAsChild(NULL
);
735 aura::client::ParentWindowWithContext(
736 view_
->GetNativeView(),
737 parent_view_
->GetNativeView()->GetRootWindow(),
739 view_
->SetSize(gfx::Size(100, 100));
741 aura::test::TestCursorClient
cursor_client(
742 parent_view_
->GetNativeView()->GetRootWindow());
744 cursor_client
.AddObserver(view_
);
746 // Expect a message the first time the cursor is shown.
748 sink_
->ClearMessages();
749 cursor_client
.ShowCursor();
750 EXPECT_EQ(1u, sink_
->message_count());
751 EXPECT_TRUE(sink_
->GetUniqueMessageMatching(
752 InputMsg_CursorVisibilityChange::ID
));
754 // No message expected if the renderer already knows the cursor is visible.
755 sink_
->ClearMessages();
756 cursor_client
.ShowCursor();
757 EXPECT_EQ(0u, sink_
->message_count());
759 // Hiding the cursor should send a message.
760 sink_
->ClearMessages();
761 cursor_client
.HideCursor();
762 EXPECT_EQ(1u, sink_
->message_count());
763 EXPECT_TRUE(sink_
->GetUniqueMessageMatching(
764 InputMsg_CursorVisibilityChange::ID
));
766 // No message expected if the renderer already knows the cursor is invisible.
767 sink_
->ClearMessages();
768 cursor_client
.HideCursor();
769 EXPECT_EQ(0u, sink_
->message_count());
771 // No messages should be sent while the view is invisible.
773 sink_
->ClearMessages();
774 cursor_client
.ShowCursor();
775 EXPECT_EQ(0u, sink_
->message_count());
776 cursor_client
.HideCursor();
777 EXPECT_EQ(0u, sink_
->message_count());
779 // Show the view. Since the cursor was invisible when the view was hidden,
780 // no message should be sent.
781 sink_
->ClearMessages();
783 EXPECT_FALSE(sink_
->GetUniqueMessageMatching(
784 InputMsg_CursorVisibilityChange::ID
));
786 // No message expected if the renderer already knows the cursor is invisible.
787 sink_
->ClearMessages();
788 cursor_client
.HideCursor();
789 EXPECT_EQ(0u, sink_
->message_count());
791 // Showing the cursor should send a message.
792 sink_
->ClearMessages();
793 cursor_client
.ShowCursor();
794 EXPECT_EQ(1u, sink_
->message_count());
795 EXPECT_TRUE(sink_
->GetUniqueMessageMatching(
796 InputMsg_CursorVisibilityChange::ID
));
798 // No messages should be sent while the view is invisible.
800 sink_
->ClearMessages();
801 cursor_client
.HideCursor();
802 EXPECT_EQ(0u, sink_
->message_count());
804 // Show the view. Since the cursor was visible when the view was hidden,
805 // a message is expected to be sent.
806 sink_
->ClearMessages();
808 EXPECT_TRUE(sink_
->GetUniqueMessageMatching(
809 InputMsg_CursorVisibilityChange::ID
));
811 cursor_client
.RemoveObserver(view_
);
814 TEST_F(RenderWidgetHostViewAuraTest
, UpdateCursorIfOverSelf
) {
815 view_
->InitAsChild(NULL
);
816 aura::client::ParentWindowWithContext(
817 view_
->GetNativeView(),
818 parent_view_
->GetNativeView()->GetRootWindow(),
821 // Note that all coordinates in this test are screen coordinates.
822 view_
->SetBounds(gfx::Rect(60, 60, 100, 100));
825 aura::test::TestCursorClient
cursor_client(
826 parent_view_
->GetNativeView()->GetRootWindow());
828 // Cursor is in the middle of the window.
829 cursor_client
.reset_calls_to_set_cursor();
830 aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(110, 110));
831 view_
->UpdateCursorIfOverSelf();
832 EXPECT_EQ(1, cursor_client
.calls_to_set_cursor());
834 // Cursor is near the top of the window.
835 cursor_client
.reset_calls_to_set_cursor();
836 aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(80, 65));
837 view_
->UpdateCursorIfOverSelf();
838 EXPECT_EQ(1, cursor_client
.calls_to_set_cursor());
840 // Cursor is near the bottom of the window.
841 cursor_client
.reset_calls_to_set_cursor();
842 aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(159, 159));
843 view_
->UpdateCursorIfOverSelf();
844 EXPECT_EQ(1, cursor_client
.calls_to_set_cursor());
846 // Cursor is above the window.
847 cursor_client
.reset_calls_to_set_cursor();
848 aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(67, 59));
849 view_
->UpdateCursorIfOverSelf();
850 EXPECT_EQ(0, cursor_client
.calls_to_set_cursor());
852 // Cursor is below the window.
853 cursor_client
.reset_calls_to_set_cursor();
854 aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(161, 161));
855 view_
->UpdateCursorIfOverSelf();
856 EXPECT_EQ(0, cursor_client
.calls_to_set_cursor());
859 scoped_ptr
<cc::CompositorFrame
> MakeDelegatedFrame(float scale_factor
,
862 scoped_ptr
<cc::CompositorFrame
> frame(new cc::CompositorFrame
);
863 frame
->metadata
.device_scale_factor
= scale_factor
;
864 frame
->delegated_frame_data
.reset(new cc::DelegatedFrameData
);
866 scoped_ptr
<cc::RenderPass
> pass
= cc::RenderPass::Create();
868 cc::RenderPass::Id(1, 1), gfx::Rect(size
), damage
, gfx::Transform());
869 frame
->delegated_frame_data
->render_pass_list
.push_back(pass
.Pass());
873 // Resizing in fullscreen mode should send the up-to-date screen info.
874 TEST_F(RenderWidgetHostViewAuraTest
, FullscreenResize
) {
875 aura::Window
* root_window
= aura_test_helper_
->root_window();
876 root_window
->SetLayoutManager(new FullscreenLayoutManager(root_window
));
877 view_
->InitAsFullscreen(parent_view_
);
879 widget_host_
->ResetSizeAndRepaintPendingFlags();
880 sink_
->ClearMessages();
882 // Call WasResized to flush the old screen info.
883 view_
->GetRenderWidgetHost()->WasResized();
885 // 0 is CreatingNew message.
886 const IPC::Message
* msg
= sink_
->GetMessageAt(0);
887 EXPECT_EQ(ViewMsg_Resize::ID
, msg
->type());
888 ViewMsg_Resize::Param params
;
889 ViewMsg_Resize::Read(msg
, ¶ms
);
890 EXPECT_EQ("0,0 800x600",
891 gfx::Rect(params
.a
.screen_info
.availableRect
).ToString());
892 EXPECT_EQ("800x600", params
.a
.new_size
.ToString());
893 // Resizes are blocked until we swapped a frame of the correct size, and
894 // we've committed it.
895 view_
->OnSwapCompositorFrame(
898 1.f
, params
.a
.new_size
, gfx::Rect(params
.a
.new_size
)));
899 ui::DrawWaiterForTest::WaitForCommit(
900 root_window
->GetHost()->compositor());
903 widget_host_
->ResetSizeAndRepaintPendingFlags();
904 sink_
->ClearMessages();
906 // Make sure the corrent screen size is set along in the resize
907 // request when the screen size has changed.
908 aura_test_helper_
->test_screen()->SetUIScale(0.5);
909 EXPECT_EQ(1u, sink_
->message_count());
911 const IPC::Message
* msg
= sink_
->GetMessageAt(0);
912 EXPECT_EQ(ViewMsg_Resize::ID
, msg
->type());
913 ViewMsg_Resize::Param params
;
914 ViewMsg_Resize::Read(msg
, ¶ms
);
915 EXPECT_EQ("0,0 1600x1200",
916 gfx::Rect(params
.a
.screen_info
.availableRect
).ToString());
917 EXPECT_EQ("1600x1200", params
.a
.new_size
.ToString());
918 view_
->OnSwapCompositorFrame(
921 1.f
, params
.a
.new_size
, gfx::Rect(params
.a
.new_size
)));
922 ui::DrawWaiterForTest::WaitForCommit(
923 root_window
->GetHost()->compositor());
927 // Swapping a frame should notify the window.
928 TEST_F(RenderWidgetHostViewAuraTest
, SwapNotifiesWindow
) {
929 gfx::Size
view_size(100, 100);
930 gfx::Rect
view_rect(view_size
);
932 view_
->InitAsChild(NULL
);
933 aura::client::ParentWindowWithContext(
934 view_
->GetNativeView(),
935 parent_view_
->GetNativeView()->GetRootWindow(),
937 view_
->SetSize(view_size
);
940 MockWindowObserver observer
;
941 view_
->window_
->AddObserver(&observer
);
943 // Delegated renderer path
944 EXPECT_CALL(observer
, OnWindowPaintScheduled(view_
->window_
, view_rect
));
945 view_
->OnSwapCompositorFrame(
946 0, MakeDelegatedFrame(1.f
, view_size
, view_rect
));
947 testing::Mock::VerifyAndClearExpectations(&observer
);
949 EXPECT_CALL(observer
, OnWindowPaintScheduled(view_
->window_
,
950 gfx::Rect(5, 5, 5, 5)));
951 view_
->OnSwapCompositorFrame(
952 0, MakeDelegatedFrame(1.f
, view_size
, gfx::Rect(5, 5, 5, 5)));
953 testing::Mock::VerifyAndClearExpectations(&observer
);
955 view_
->window_
->RemoveObserver(&observer
);
958 // Skipped frames should not drop their damage.
959 TEST_F(RenderWidgetHostViewAuraTest
, SkippedDelegatedFrames
) {
960 gfx::Rect
view_rect(100, 100);
961 gfx::Size frame_size
= view_rect
.size();
963 view_
->InitAsChild(NULL
);
964 aura::client::ParentWindowWithContext(
965 view_
->GetNativeView(),
966 parent_view_
->GetNativeView()->GetRootWindow(),
968 view_
->SetSize(view_rect
.size());
970 MockWindowObserver observer
;
971 view_
->window_
->AddObserver(&observer
);
973 // A full frame of damage.
974 EXPECT_CALL(observer
, OnWindowPaintScheduled(view_
->window_
, view_rect
));
975 view_
->OnSwapCompositorFrame(
976 0, MakeDelegatedFrame(1.f
, frame_size
, view_rect
));
977 testing::Mock::VerifyAndClearExpectations(&observer
);
978 view_
->RunOnCompositingDidCommit();
980 // A partial damage frame.
981 gfx::Rect
partial_view_rect(30, 30, 20, 20);
982 EXPECT_CALL(observer
,
983 OnWindowPaintScheduled(view_
->window_
, partial_view_rect
));
984 view_
->OnSwapCompositorFrame(
985 0, MakeDelegatedFrame(1.f
, frame_size
, partial_view_rect
));
986 testing::Mock::VerifyAndClearExpectations(&observer
);
987 view_
->RunOnCompositingDidCommit();
989 // Lock the compositor. Now we should drop frames.
990 view_rect
= gfx::Rect(150, 150);
991 view_
->SetSize(view_rect
.size());
992 view_
->GetDelegatedFrameHost()->MaybeCreateResizeLock();
994 // This frame is dropped.
995 gfx::Rect
dropped_damage_rect_1(10, 20, 30, 40);
996 EXPECT_CALL(observer
, OnWindowPaintScheduled(_
, _
)).Times(0);
997 view_
->OnSwapCompositorFrame(
998 0, MakeDelegatedFrame(1.f
, frame_size
, dropped_damage_rect_1
));
999 testing::Mock::VerifyAndClearExpectations(&observer
);
1000 view_
->RunOnCompositingDidCommit();
1002 gfx::Rect
dropped_damage_rect_2(40, 50, 10, 20);
1003 EXPECT_CALL(observer
, OnWindowPaintScheduled(_
, _
)).Times(0);
1004 view_
->OnSwapCompositorFrame(
1005 0, MakeDelegatedFrame(1.f
, frame_size
, dropped_damage_rect_2
));
1006 testing::Mock::VerifyAndClearExpectations(&observer
);
1007 view_
->RunOnCompositingDidCommit();
1009 // Unlock the compositor. This frame should damage everything.
1010 frame_size
= view_rect
.size();
1012 gfx::Rect
new_damage_rect(5, 6, 10, 10);
1013 EXPECT_CALL(observer
,
1014 OnWindowPaintScheduled(view_
->window_
, view_rect
));
1015 view_
->OnSwapCompositorFrame(
1016 0, MakeDelegatedFrame(1.f
, frame_size
, new_damage_rect
));
1017 testing::Mock::VerifyAndClearExpectations(&observer
);
1018 view_
->RunOnCompositingDidCommit();
1020 // A partial damage frame, this should not be dropped.
1021 EXPECT_CALL(observer
,
1022 OnWindowPaintScheduled(view_
->window_
, partial_view_rect
));
1023 view_
->OnSwapCompositorFrame(
1024 0, MakeDelegatedFrame(1.f
, frame_size
, partial_view_rect
));
1025 testing::Mock::VerifyAndClearExpectations(&observer
);
1026 view_
->RunOnCompositingDidCommit();
1029 view_
->window_
->RemoveObserver(&observer
);
1032 TEST_F(RenderWidgetHostViewAuraTest
, OutputSurfaceIdChange
) {
1033 gfx::Rect
view_rect(100, 100);
1034 gfx::Size frame_size
= view_rect
.size();
1036 view_
->InitAsChild(NULL
);
1037 aura::client::ParentWindowWithContext(
1038 view_
->GetNativeView(),
1039 parent_view_
->GetNativeView()->GetRootWindow(),
1041 view_
->SetSize(view_rect
.size());
1043 MockWindowObserver observer
;
1044 view_
->window_
->AddObserver(&observer
);
1047 EXPECT_CALL(observer
, OnWindowPaintScheduled(view_
->window_
, view_rect
));
1048 view_
->OnSwapCompositorFrame(
1049 0, MakeDelegatedFrame(1.f
, frame_size
, view_rect
));
1050 testing::Mock::VerifyAndClearExpectations(&observer
);
1051 view_
->RunOnCompositingDidCommit();
1053 // Swap a frame with a different surface id.
1054 EXPECT_CALL(observer
, OnWindowPaintScheduled(view_
->window_
, view_rect
));
1055 view_
->OnSwapCompositorFrame(
1056 1, MakeDelegatedFrame(1.f
, frame_size
, view_rect
));
1057 testing::Mock::VerifyAndClearExpectations(&observer
);
1058 view_
->RunOnCompositingDidCommit();
1060 // Swap an empty frame, with a different surface id.
1061 view_
->OnSwapCompositorFrame(
1062 2, MakeDelegatedFrame(1.f
, gfx::Size(), gfx::Rect()));
1063 testing::Mock::VerifyAndClearExpectations(&observer
);
1064 view_
->RunOnCompositingDidCommit();
1066 // Swap another frame, with a different surface id.
1067 EXPECT_CALL(observer
, OnWindowPaintScheduled(view_
->window_
, view_rect
));
1068 view_
->OnSwapCompositorFrame(3,
1069 MakeDelegatedFrame(1.f
, frame_size
, view_rect
));
1070 testing::Mock::VerifyAndClearExpectations(&observer
);
1071 view_
->RunOnCompositingDidCommit();
1073 view_
->window_
->RemoveObserver(&observer
);
1076 TEST_F(RenderWidgetHostViewAuraTest
, DiscardDelegatedFrames
) {
1077 size_t max_renderer_frames
=
1078 RendererFrameManager::GetInstance()->max_number_of_saved_frames();
1079 ASSERT_LE(2u, max_renderer_frames
);
1080 size_t renderer_count
= max_renderer_frames
+ 1;
1081 gfx::Rect
view_rect(100, 100);
1082 gfx::Size frame_size
= view_rect
.size();
1083 DCHECK_EQ(0u, HostSharedBitmapManager::current()->AllocatedBitmapCount());
1085 scoped_ptr
<RenderWidgetHostImpl
* []> hosts(
1086 new RenderWidgetHostImpl
* [renderer_count
]);
1087 scoped_ptr
<FakeRenderWidgetHostViewAura
* []> views(
1088 new FakeRenderWidgetHostViewAura
* [renderer_count
]);
1090 // Create a bunch of renderers.
1091 for (size_t i
= 0; i
< renderer_count
; ++i
) {
1092 hosts
[i
] = new RenderWidgetHostImpl(
1093 &delegate_
, process_host_
, MSG_ROUTING_NONE
, false);
1095 hosts
[i
]->OnMessageReceived(
1096 ViewHostMsg_DidActivateAcceleratedCompositing(0, true));
1097 views
[i
] = new FakeRenderWidgetHostViewAura(hosts
[i
]);
1098 views
[i
]->InitAsChild(NULL
);
1099 aura::client::ParentWindowWithContext(
1100 views
[i
]->GetNativeView(),
1101 parent_view_
->GetNativeView()->GetRootWindow(),
1103 views
[i
]->SetSize(view_rect
.size());
1106 // Make each renderer visible, and swap a frame on it, then make it invisible.
1107 for (size_t i
= 0; i
< renderer_count
; ++i
) {
1108 views
[i
]->WasShown();
1109 views
[i
]->OnSwapCompositorFrame(
1110 1, MakeDelegatedFrame(1.f
, frame_size
, view_rect
));
1111 EXPECT_TRUE(views
[i
]->frame_provider());
1112 views
[i
]->WasHidden();
1115 // There should be max_renderer_frames with a frame in it, and one without it.
1116 // Since the logic is LRU eviction, the first one should be without.
1117 EXPECT_FALSE(views
[0]->frame_provider());
1118 for (size_t i
= 1; i
< renderer_count
; ++i
)
1119 EXPECT_TRUE(views
[i
]->frame_provider());
1121 // LRU renderer is [0], make it visible, it shouldn't evict anything yet.
1122 views
[0]->WasShown();
1123 EXPECT_FALSE(views
[0]->frame_provider());
1124 EXPECT_TRUE(views
[1]->frame_provider());
1126 // Swap a frame on it, it should evict the next LRU [1].
1127 views
[0]->OnSwapCompositorFrame(
1128 1, MakeDelegatedFrame(1.f
, frame_size
, view_rect
));
1129 EXPECT_TRUE(views
[0]->frame_provider());
1130 EXPECT_FALSE(views
[1]->frame_provider());
1131 views
[0]->WasHidden();
1133 // LRU renderer is [1], still hidden. Swap a frame on it, it should evict
1134 // the next LRU [2].
1135 views
[1]->OnSwapCompositorFrame(
1136 1, MakeDelegatedFrame(1.f
, frame_size
, view_rect
));
1137 EXPECT_TRUE(views
[0]->frame_provider());
1138 EXPECT_TRUE(views
[1]->frame_provider());
1139 EXPECT_FALSE(views
[2]->frame_provider());
1140 for (size_t i
= 3; i
< renderer_count
; ++i
)
1141 EXPECT_TRUE(views
[i
]->frame_provider());
1143 // Make all renderers but [0] visible and swap a frame on them, keep [0]
1144 // hidden, it becomes the LRU.
1145 for (size_t i
= 1; i
< renderer_count
; ++i
) {
1146 views
[i
]->WasShown();
1147 views
[i
]->OnSwapCompositorFrame(
1148 1, MakeDelegatedFrame(1.f
, frame_size
, view_rect
));
1149 EXPECT_TRUE(views
[i
]->frame_provider());
1151 EXPECT_FALSE(views
[0]->frame_provider());
1153 // Swap a frame on [0], it should be evicted immediately.
1154 views
[0]->OnSwapCompositorFrame(
1155 1, MakeDelegatedFrame(1.f
, frame_size
, view_rect
));
1156 EXPECT_FALSE(views
[0]->frame_provider());
1158 // Make [0] visible, and swap a frame on it. Nothing should be evicted
1159 // although we're above the limit.
1160 views
[0]->WasShown();
1161 views
[0]->OnSwapCompositorFrame(
1162 1, MakeDelegatedFrame(1.f
, frame_size
, view_rect
));
1163 for (size_t i
= 0; i
< renderer_count
; ++i
)
1164 EXPECT_TRUE(views
[i
]->frame_provider());
1166 // Make [0] hidden, it should evict its frame.
1167 views
[0]->WasHidden();
1168 EXPECT_FALSE(views
[0]->frame_provider());
1170 for (size_t i
= 0; i
< renderer_count
- 1; ++i
)
1171 views
[i
]->WasHidden();
1173 // Allocate enough bitmaps so that two frames (proportionally) would be
1174 // enough hit the handle limit.
1175 int handles_per_frame
= 5;
1176 RendererFrameManager::GetInstance()->set_max_handles(handles_per_frame
* 2);
1178 for (size_t i
= 0; i
< (renderer_count
- 1) * handles_per_frame
; i
++) {
1179 HostSharedBitmapManager::current()->ChildAllocatedSharedBitmap(
1181 base::SharedMemory::NULLHandle(),
1182 base::GetCurrentProcessHandle(),
1183 cc::SharedBitmap::GenerateId());
1186 // Hiding this last bitmap should evict all but two frames.
1187 views
[renderer_count
- 1]->WasHidden();
1188 for (size_t i
= 0; i
< renderer_count
; ++i
) {
1189 if (i
+ 2 < renderer_count
)
1190 EXPECT_FALSE(views
[i
]->frame_provider());
1192 EXPECT_TRUE(views
[i
]->frame_provider());
1194 HostSharedBitmapManager::current()->ProcessRemoved(
1195 base::GetCurrentProcessHandle());
1196 RendererFrameManager::GetInstance()->set_max_handles(
1197 base::SharedMemory::GetHandleLimit());
1199 for (size_t i
= 0; i
< renderer_count
; ++i
) {
1200 views
[i
]->Destroy();
1205 TEST_F(RenderWidgetHostViewAuraTest
, DiscardDelegatedFramesWithLocking
) {
1206 size_t max_renderer_frames
=
1207 RendererFrameManager::GetInstance()->max_number_of_saved_frames();
1208 ASSERT_LE(2u, max_renderer_frames
);
1209 size_t renderer_count
= max_renderer_frames
+ 1;
1210 gfx::Rect
view_rect(100, 100);
1211 gfx::Size frame_size
= view_rect
.size();
1212 DCHECK_EQ(0u, HostSharedBitmapManager::current()->AllocatedBitmapCount());
1214 scoped_ptr
<RenderWidgetHostImpl
* []> hosts(
1215 new RenderWidgetHostImpl
* [renderer_count
]);
1216 scoped_ptr
<FakeRenderWidgetHostViewAura
* []> views(
1217 new FakeRenderWidgetHostViewAura
* [renderer_count
]);
1219 // Create a bunch of renderers.
1220 for (size_t i
= 0; i
< renderer_count
; ++i
) {
1221 hosts
[i
] = new RenderWidgetHostImpl(
1222 &delegate_
, process_host_
, MSG_ROUTING_NONE
, false);
1224 hosts
[i
]->OnMessageReceived(
1225 ViewHostMsg_DidActivateAcceleratedCompositing(0, true));
1226 views
[i
] = new FakeRenderWidgetHostViewAura(hosts
[i
]);
1227 views
[i
]->InitAsChild(NULL
);
1228 aura::client::ParentWindowWithContext(
1229 views
[i
]->GetNativeView(),
1230 parent_view_
->GetNativeView()->GetRootWindow(),
1232 views
[i
]->SetSize(view_rect
.size());
1235 // Make each renderer visible and swap a frame on it. No eviction should
1236 // occur because all frames are visible.
1237 for (size_t i
= 0; i
< renderer_count
; ++i
) {
1238 views
[i
]->WasShown();
1239 views
[i
]->OnSwapCompositorFrame(
1240 1, MakeDelegatedFrame(1.f
, frame_size
, view_rect
));
1241 EXPECT_TRUE(views
[i
]->frame_provider());
1244 // If we hide [0], then [0] should be evicted.
1245 views
[0]->WasHidden();
1246 EXPECT_FALSE(views
[0]->frame_provider());
1248 // If we lock [0] before hiding it, then [0] should not be evicted.
1249 views
[0]->WasShown();
1250 views
[0]->OnSwapCompositorFrame(
1251 1, MakeDelegatedFrame(1.f
, frame_size
, view_rect
));
1252 EXPECT_TRUE(views
[0]->frame_provider());
1253 views
[0]->GetDelegatedFrameHost()->LockResources();
1254 views
[0]->WasHidden();
1255 EXPECT_TRUE(views
[0]->frame_provider());
1257 // If we unlock [0] now, then [0] should be evicted.
1258 views
[0]->GetDelegatedFrameHost()->UnlockResources();
1259 EXPECT_FALSE(views
[0]->frame_provider());
1261 for (size_t i
= 0; i
< renderer_count
; ++i
) {
1262 views
[i
]->Destroy();
1267 TEST_F(RenderWidgetHostViewAuraTest
, SoftwareDPIChange
) {
1268 gfx::Rect
view_rect(100, 100);
1269 gfx::Size
frame_size(100, 100);
1271 view_
->InitAsChild(NULL
);
1272 aura::client::ParentWindowWithContext(
1273 view_
->GetNativeView(),
1274 parent_view_
->GetNativeView()->GetRootWindow(),
1276 view_
->SetSize(view_rect
.size());
1279 // With a 1x DPI UI and 1x DPI Renderer.
1280 view_
->OnSwapCompositorFrame(
1281 1, MakeDelegatedFrame(1.f
, frame_size
, gfx::Rect(frame_size
)));
1283 // Save the frame provider.
1284 scoped_refptr
<cc::DelegatedFrameProvider
> frame_provider
=
1285 view_
->frame_provider();
1287 // This frame will have the same number of physical pixels, but has a new
1289 view_
->OnSwapCompositorFrame(
1290 1, MakeDelegatedFrame(2.f
, frame_size
, gfx::Rect(frame_size
)));
1292 // When we get a new frame with the same frame size in physical pixels, but a
1293 // different scale, we should generate a new frame provider, as the final
1294 // result will need to be scaled differently to the screen.
1295 EXPECT_NE(frame_provider
.get(), view_
->frame_provider());
1298 class RenderWidgetHostViewAuraCopyRequestTest
1299 : public RenderWidgetHostViewAuraShutdownTest
{
1301 RenderWidgetHostViewAuraCopyRequestTest()
1302 : callback_count_(0), result_(false) {}
1304 void CallbackMethod(const base::Closure
& quit_closure
, bool result
) {
1310 int callback_count_
;
1314 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAuraCopyRequestTest
);
1317 TEST_F(RenderWidgetHostViewAuraCopyRequestTest
, DestroyedAfterCopyRequest
) {
1318 base::RunLoop run_loop
;
1320 gfx::Rect
view_rect(100, 100);
1321 scoped_ptr
<cc::CopyOutputRequest
> request
;
1323 view_
->InitAsChild(NULL
);
1324 aura::client::ParentWindowWithContext(
1325 view_
->GetNativeView(),
1326 parent_view_
->GetNativeView()->GetRootWindow(),
1328 view_
->SetSize(view_rect
.size());
1331 scoped_ptr
<FakeFrameSubscriber
> frame_subscriber(new FakeFrameSubscriber(
1333 base::Bind(&RenderWidgetHostViewAuraCopyRequestTest::CallbackMethod
,
1334 base::Unretained(this),
1335 run_loop
.QuitClosure())));
1337 EXPECT_EQ(0, callback_count_
);
1338 EXPECT_FALSE(view_
->last_copy_request_
);
1340 view_
->BeginFrameSubscription(
1341 frame_subscriber
.PassAs
<RenderWidgetHostViewFrameSubscriber
>());
1342 view_
->OnSwapCompositorFrame(
1343 1, MakeDelegatedFrame(1.f
, view_rect
.size(), gfx::Rect(view_rect
)));
1345 EXPECT_EQ(0, callback_count_
);
1346 EXPECT_TRUE(view_
->last_copy_request_
);
1347 EXPECT_TRUE(view_
->last_copy_request_
->has_texture_mailbox());
1348 request
= view_
->last_copy_request_
.Pass();
1350 // There should be one subscriber texture in flight.
1352 view_
->GetDelegatedFrameHost()->
1353 active_frame_subscriber_textures_
.size());
1355 // Send back the mailbox included in the request. There's no release callback
1356 // since the mailbox came from the RWHVA originally.
1357 request
->SendTextureResult(view_rect
.size(),
1358 request
->texture_mailbox(),
1359 scoped_ptr
<cc::SingleReleaseCallback
>());
1361 // This runs until the callback happens.
1364 // The callback should succeed.
1366 view_
->GetDelegatedFrameHost()->
1367 active_frame_subscriber_textures_
.size());
1368 EXPECT_EQ(1, callback_count_
);
1369 EXPECT_TRUE(result_
);
1371 view_
->OnSwapCompositorFrame(
1372 1, MakeDelegatedFrame(1.f
, view_rect
.size(), gfx::Rect(view_rect
)));
1374 EXPECT_EQ(1, callback_count_
);
1375 request
= view_
->last_copy_request_
.Pass();
1377 // There should be one subscriber texture in flight again.
1379 view_
->GetDelegatedFrameHost()->
1380 active_frame_subscriber_textures_
.size());
1382 // Destroy the RenderWidgetHostViewAura and ImageTransportFactory.
1383 TearDownEnvironment();
1385 // Send back the mailbox included in the request. There's no release callback
1386 // since the mailbox came from the RWHVA originally.
1387 request
->SendTextureResult(view_rect
.size(),
1388 request
->texture_mailbox(),
1389 scoped_ptr
<cc::SingleReleaseCallback
>());
1391 // Because the copy request callback may be holding state within it, that
1392 // state must handle the RWHVA and ImageTransportFactory going away before the
1393 // callback is called. This test passes if it does not crash as a result of
1394 // these things being destroyed.
1395 EXPECT_EQ(2, callback_count_
);
1396 EXPECT_FALSE(result_
);
1399 TEST_F(RenderWidgetHostViewAuraTest
, VisibleViewportTest
) {
1400 gfx::Rect
view_rect(100, 100);
1402 view_
->InitAsChild(NULL
);
1403 aura::client::ParentWindowWithContext(
1404 view_
->GetNativeView(),
1405 parent_view_
->GetNativeView()->GetRootWindow(),
1407 view_
->SetSize(view_rect
.size());
1410 // Defaults to full height of the view.
1411 EXPECT_EQ(100, view_
->GetVisibleViewportSize().height());
1413 widget_host_
->ResetSizeAndRepaintPendingFlags();
1414 sink_
->ClearMessages();
1415 view_
->SetInsets(gfx::Insets(0, 0, 40, 0));
1417 EXPECT_EQ(60, view_
->GetVisibleViewportSize().height());
1419 const IPC::Message
*message
= sink_
->GetFirstMessageMatching(
1420 ViewMsg_Resize::ID
);
1421 ASSERT_TRUE(message
!= NULL
);
1423 ViewMsg_Resize::Param params
;
1424 ViewMsg_Resize::Read(message
, ¶ms
);
1425 EXPECT_EQ(60, params
.a
.visible_viewport_size
.height());
1428 } // namespace content