Revert 268405 "Make sure that ScratchBuffer::Allocate() always r..."
[chromium-blink-merge.git] / content / browser / renderer_host / render_widget_host_view_aura_unittest.cc
blob581ebc8c120db70e0d3346cd0214b17b56e34913
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"
52 using testing::_;
54 namespace content {
55 namespace {
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() {}
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 {
72 point->Offset(1, 1);
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 {
87 public:
88 MockRenderWidgetHostDelegate() {}
89 virtual ~MockRenderWidgetHostDelegate() {}
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);
99 virtual ~TestWindowObserver() {
100 if (window_)
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_);
109 destroyed_ = true;
110 window_ = NULL;
113 private:
114 // Window that we're observing, or NULL if it's been destroyed.
115 aura::Window* window_;
117 // Was |window_| destroyed?
118 bool destroyed_;
120 DISALLOW_COPY_AND_ASSIGN(TestWindowObserver);
123 class FakeFrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
124 public:
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,
132 size_,
133 gfx::Rect(size_),
134 size_,
135 base::TimeDelta());
136 *callback = base::Bind(&FakeFrameSubscriber::CallbackMethod, callback_);
137 return true;
140 static void CallbackMethod(base::Callback<void(bool)> callback,
141 base::TimeTicks timestamp,
142 bool success) {
143 callback.Run(success);
146 private:
147 gfx::Size size_;
148 base::Callback<void(bool)> callback_;
151 class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
152 public:
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)
177 OVERRIDE {
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
195 // time out.
196 class FakeResizeLock : public ResizeLock {
197 public:
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 {
208 public:
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(),
230 gfx::Rect());
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() {
241 sink_ = NULL;
242 process_host_ = NULL;
243 if (view_)
244 view_->Destroy();
245 delete widget_host_;
247 parent_view_->Destroy();
248 delete parent_host_;
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(); }
262 protected:
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
271 // destruction.
272 RenderWidgetHostImpl* parent_host_;
273 RenderWidgetHostViewAura* parent_view_;
275 // Tests should set these to NULL if they've already triggered their
276 // destruction.
277 RenderWidgetHostImpl* widget_host_;
278 FakeRenderWidgetHostViewAura* view_;
280 IPC::TestSink* sink_;
282 private:
283 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAuraTest);
286 class RenderWidgetHostViewAuraShutdownTest
287 : public RenderWidgetHostViewAuraTest {
288 public:
289 RenderWidgetHostViewAuraShutdownTest() {}
291 virtual void TearDown() OVERRIDE {
292 // No TearDownEnvironment here, we do this explicitly during the test.
295 private:
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 {
301 public:
302 explicit FullscreenLayoutManager(aura::Window* owner)
303 : owner_(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()));
328 private:
329 aura::Window* owner_;
330 DISALLOW_COPY_AND_ASSIGN(FullscreenLayoutManager);
333 class MockWindowObserver : public aura::WindowObserver {
334 public:
335 MOCK_METHOD2(OnWindowPaintScheduled, void(aura::Window*, const gfx::Rect&));
338 } // namespace
340 // Checks that a fullscreen view has the correct show-state and receives the
341 // focus.
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
403 // destroyed.
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);
408 sibling->Show();
409 window->parent()->AddChild(sibling.get());
410 sibling->Focus();
411 ASSERT_TRUE(sibling->HasFocus());
412 ASSERT_TRUE(observer.destroyed());
414 widget_host_ = NULL;
415 view_ = NULL;
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());
441 widget_host_ = NULL;
442 view_ = NULL;
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());
468 widget_host_ = NULL;
469 view_ = NULL;
472 // Checks that IME-composition-event state is maintained correctly.
473 TEST_F(RenderWidgetHostViewAuraTest, SetCompositionText) {
474 view_->InitAsChild(NULL);
475 view_->Show();
477 ui::CompositionText composition_text;
478 composition_text.text = base::ASCIIToUTF16("|a|b");
480 // Focused segment
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, &params);
503 // composition text
504 EXPECT_EQ(composition_text.text, params.a);
505 // underlines
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);
513 // highlighted range
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);
525 view_->Show();
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,
532 gfx::Point(30, 30),
534 ui::EventTimeForNow());
535 ui::TouchEvent move(ui::ET_TOUCH_MOVED,
536 gfx::Point(20, 20),
538 ui::EventTimeForNow());
539 ui::TouchEvent release(ui::ET_TOUCH_RELEASED,
540 gfx::Point(20, 20),
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);
626 view_->Show();
628 widget_host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true));
629 EXPECT_TRUE(widget_host_->ShouldForwardTouchEvent());
631 ui::TouchEvent press(ui::ET_TOUCH_PRESSED,
632 gfx::Point(30, 30),
634 ui::EventTimeForNow());
635 ui::TouchEvent move(ui::ET_TOUCH_MOVED,
636 gfx::Point(20, 20),
638 ui::EventTimeForNow());
639 ui::TouchEvent release(ui::ET_TOUCH_RELEASED,
640 gfx::Point(20, 20),
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(),
678 gfx::Rect());
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, &params);
689 EXPECT_EQ("100x100", params.a.new_size.ToString()); // dip size
690 EXPECT_EQ("100x100",
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, &params);
706 EXPECT_EQ(2.0f, params.a.screen_info.deviceScaleFactor);
707 EXPECT_EQ("100x100", params.a.new_size.ToString()); // dip size
708 EXPECT_EQ("200x200",
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, &params);
724 EXPECT_EQ(1.0f, params.a.screen_info.deviceScaleFactor);
725 EXPECT_EQ("100x100", params.a.new_size.ToString()); // dip size
726 EXPECT_EQ("100x100",
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(),
738 gfx::Rect());
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.
747 view_->WasShown();
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.
772 view_->WasHidden();
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();
782 view_->WasShown();
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.
799 view_->WasHidden();
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();
807 view_->WasShown();
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(),
819 gfx::Rect());
821 // Note that all coordinates in this test are screen coordinates.
822 view_->SetBounds(gfx::Rect(60, 60, 100, 100));
823 view_->Show();
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,
860 gfx::Size size,
861 gfx::Rect damage) {
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();
867 pass->SetNew(
868 cc::RenderPass::Id(1, 1), gfx::Rect(size), damage, gfx::Transform());
869 frame->delegated_frame_data->render_pass_list.push_back(pass.Pass());
870 return frame.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_);
878 view_->WasShown();
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, &params);
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(
897 MakeDelegatedFrame(
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, &params);
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(
920 MakeDelegatedFrame(
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(),
936 gfx::Rect());
937 view_->SetSize(view_size);
938 view_->WasShown();
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(),
967 gfx::Rect());
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(),
1040 gfx::Rect());
1041 view_->SetSize(view_rect.size());
1043 MockWindowObserver observer;
1044 view_->window_->AddObserver(&observer);
1046 // Swap a frame.
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);
1094 hosts[i]->Init();
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(),
1102 gfx::Rect());
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());
1191 else
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();
1201 delete hosts[i];
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);
1223 hosts[i]->Init();
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(),
1231 gfx::Rect());
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();
1263 delete hosts[i];
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(),
1275 gfx::Rect());
1276 view_->SetSize(view_rect.size());
1277 view_->WasShown();
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
1288 // scale on it.
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 {
1300 public:
1301 RenderWidgetHostViewAuraCopyRequestTest()
1302 : callback_count_(0), result_(false) {}
1304 void CallbackMethod(const base::Closure& quit_closure, bool result) {
1305 result_ = result;
1306 callback_count_++;
1307 quit_closure.Run();
1310 int callback_count_;
1311 bool result_;
1313 private:
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(),
1327 gfx::Rect());
1328 view_->SetSize(view_rect.size());
1329 view_->WasShown();
1331 scoped_ptr<FakeFrameSubscriber> frame_subscriber(new FakeFrameSubscriber(
1332 view_rect.size(),
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.
1351 EXPECT_EQ(1u,
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.
1362 run_loop.Run();
1364 // The callback should succeed.
1365 EXPECT_EQ(0u,
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.
1378 EXPECT_EQ(1u,
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(),
1406 gfx::Rect());
1407 view_->SetSize(view_rect.size());
1408 view_->WasShown();
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, &params);
1425 EXPECT_EQ(60, params.a.visible_viewport_size.height());
1428 } // namespace content