Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(111)

Side by Side Diff: chrome/browser/renderer_host/render_widget_host_unittest.cc

Issue 6532073: Move core pieces of browser\renderer_host to src\content. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/basictypes.h"
6 #include "base/scoped_ptr.h"
7 #include "base/shared_memory.h"
8 #include "base/timer.h"
9 #include "build/build_config.h"
10 #include "chrome/browser/renderer_host/backing_store.h"
11 #include "chrome/browser/renderer_host/test/test_render_view_host.h"
12 #include "chrome/common/notification_details.h"
13 #include "chrome/common/notification_source.h"
14 #include "chrome/common/render_messages.h"
15 #include "chrome/common/render_messages_params.h"
16 #include "chrome/test/testing_profile.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "ui/base/keycodes/keyboard_codes.h"
19 #include "ui/gfx/canvas_skia.h"
20
21 using base::TimeDelta;
22
23 using WebKit::WebInputEvent;
24 using WebKit::WebMouseWheelEvent;
25
26 namespace gfx {
27 class Size;
28 }
29
30 // RenderWidgetHostProcess -----------------------------------------------------
31
32 class RenderWidgetHostProcess : public MockRenderProcessHost {
33 public:
34 explicit RenderWidgetHostProcess(Profile* profile)
35 : MockRenderProcessHost(profile),
36 current_update_buf_(NULL),
37 update_msg_should_reply_(false),
38 update_msg_reply_flags_(0) {
39 // DANGER! This is a hack. The RenderWidgetHost checks the channel to see
40 // if the process is still alive, but it doesn't actually dereference it.
41 // An IPC::SyncChannel is nontrivial, so we just fake it here. If you end up
42 // crashing by dereferencing 1, then you'll have to make a real channel.
43 channel_.reset(reinterpret_cast<IPC::SyncChannel*>(0x1));
44 }
45 ~RenderWidgetHostProcess() {
46 // We don't want to actually delete the channel, since it's not a real
47 // pointer.
48 ignore_result(channel_.release());
49 delete current_update_buf_;
50 }
51
52 void set_update_msg_should_reply(bool reply) {
53 update_msg_should_reply_ = reply;
54 }
55 void set_update_msg_reply_flags(int flags) {
56 update_msg_reply_flags_ = flags;
57 }
58
59 // Fills the given update parameters with resonable default values.
60 void InitUpdateRectParams(ViewHostMsg_UpdateRect_Params* params);
61
62 protected:
63 virtual bool WaitForUpdateMsg(int render_widget_id,
64 const base::TimeDelta& max_delay,
65 IPC::Message* msg);
66
67 TransportDIB* current_update_buf_;
68
69 // Set to true when WaitForUpdateMsg should return a successful update message
70 // reply. False implies timeout.
71 bool update_msg_should_reply_;
72
73 // Indicates the flags that should be sent with a the repaint request. This
74 // only has an effect when update_msg_should_reply_ is true.
75 int update_msg_reply_flags_;
76
77 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostProcess);
78 };
79
80 void RenderWidgetHostProcess::InitUpdateRectParams(
81 ViewHostMsg_UpdateRect_Params* params) {
82 // Create the shared backing store.
83 const int w = 100, h = 100;
84 const size_t pixel_size = w * h * 4;
85
86 if (!current_update_buf_)
87 current_update_buf_ = TransportDIB::Create(pixel_size, 0);
88 params->bitmap = current_update_buf_->id();
89 params->bitmap_rect = gfx::Rect(0, 0, w, h);
90 params->dx = 0;
91 params->dy = 0;
92 params->copy_rects.push_back(params->bitmap_rect);
93 params->view_size = gfx::Size(w, h);
94 params->flags = update_msg_reply_flags_;
95 }
96
97 bool RenderWidgetHostProcess::WaitForUpdateMsg(int render_widget_id,
98 const base::TimeDelta& max_delay,
99 IPC::Message* msg) {
100 if (!update_msg_should_reply_)
101 return false;
102
103 // Construct a fake update reply.
104 ViewHostMsg_UpdateRect_Params params;
105 InitUpdateRectParams(&params);
106
107 ViewHostMsg_UpdateRect message(render_widget_id, params);
108 *msg = message;
109 return true;
110 }
111
112 // TestView --------------------------------------------------------------------
113
114 // This test view allows us to specify the size.
115 class TestView : public TestRenderWidgetHostView {
116 public:
117 explicit TestView(RenderWidgetHost* rwh) : TestRenderWidgetHostView(rwh) {}
118
119 // Sets the bounds returned by GetViewBounds.
120 void set_bounds(const gfx::Rect& bounds) {
121 bounds_ = bounds;
122 }
123
124 // RenderWidgetHostView override.
125 virtual gfx::Rect GetViewBounds() const {
126 return bounds_;
127 }
128
129 #if defined(OS_MACOSX)
130 virtual gfx::Rect GetViewCocoaBounds() const {
131 return bounds_;
132 }
133 #endif
134
135 protected:
136 gfx::Rect bounds_;
137 DISALLOW_COPY_AND_ASSIGN(TestView);
138 };
139
140 // MockRenderWidgetHost ----------------------------------------------------
141
142 class MockRenderWidgetHost : public RenderWidgetHost {
143 public:
144 MockRenderWidgetHost(RenderProcessHost* process, int routing_id)
145 : RenderWidgetHost(process, routing_id),
146 prehandle_keyboard_event_(false),
147 prehandle_keyboard_event_called_(false),
148 prehandle_keyboard_event_type_(WebInputEvent::Undefined),
149 unhandled_keyboard_event_called_(false),
150 unhandled_keyboard_event_type_(WebInputEvent::Undefined),
151 unresponsive_timer_fired_(false) {
152 }
153
154 // Tests that make sure we ignore keyboard event acknowledgments to events we
155 // didn't send work by making sure we didn't call UnhandledKeyboardEvent().
156 bool unhandled_keyboard_event_called() const {
157 return unhandled_keyboard_event_called_;
158 }
159
160 WebInputEvent::Type unhandled_keyboard_event_type() const {
161 return unhandled_keyboard_event_type_;
162 }
163
164 bool prehandle_keyboard_event_called() const {
165 return prehandle_keyboard_event_called_;
166 }
167
168 WebInputEvent::Type prehandle_keyboard_event_type() const {
169 return prehandle_keyboard_event_type_;
170 }
171
172 void set_prehandle_keyboard_event(bool handle) {
173 prehandle_keyboard_event_ = handle;
174 }
175
176 bool unresponsive_timer_fired() const {
177 return unresponsive_timer_fired_;
178 }
179
180 protected:
181 virtual bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
182 bool* is_keyboard_shortcut) {
183 prehandle_keyboard_event_type_ = event.type;
184 prehandle_keyboard_event_called_ = true;
185 return prehandle_keyboard_event_;
186 }
187
188 virtual void UnhandledKeyboardEvent(const NativeWebKeyboardEvent& event) {
189 unhandled_keyboard_event_type_ = event.type;
190 unhandled_keyboard_event_called_ = true;
191 }
192
193 virtual void NotifyRendererUnresponsive() {
194 unresponsive_timer_fired_ = true;
195 }
196
197 private:
198 bool prehandle_keyboard_event_;
199 bool prehandle_keyboard_event_called_;
200 WebInputEvent::Type prehandle_keyboard_event_type_;
201
202 bool unhandled_keyboard_event_called_;
203 WebInputEvent::Type unhandled_keyboard_event_type_;
204
205 bool unresponsive_timer_fired_;
206 };
207
208 // MockPaintingObserver --------------------------------------------------------
209
210 class MockPaintingObserver : public NotificationObserver {
211 public:
212 void WidgetDidReceivePaintAtSizeAck(RenderWidgetHost* host,
213 int tag,
214 const gfx::Size& size) {
215 host_ = reinterpret_cast<MockRenderWidgetHost*>(host);
216 tag_ = tag;
217 size_ = size;
218 }
219
220 void Observe(NotificationType type,
221 const NotificationSource& source,
222 const NotificationDetails& details) {
223 if (type ==
224 NotificationType::RENDER_WIDGET_HOST_DID_RECEIVE_PAINT_AT_SIZE_ACK) {
225 RenderWidgetHost::PaintAtSizeAckDetails* size_ack_details =
226 Details<RenderWidgetHost::PaintAtSizeAckDetails>(details).ptr();
227 WidgetDidReceivePaintAtSizeAck(
228 Source<RenderWidgetHost>(source).ptr(),
229 size_ack_details->tag,
230 size_ack_details->size);
231 }
232 }
233
234 MockRenderWidgetHost* host() const { return host_; }
235 int tag() const { return tag_; }
236 gfx::Size size() const { return size_; }
237
238 private:
239 MockRenderWidgetHost* host_;
240 int tag_;
241 gfx::Size size_;
242 };
243
244
245 // RenderWidgetHostTest --------------------------------------------------------
246
247 class RenderWidgetHostTest : public testing::Test {
248 public:
249 RenderWidgetHostTest() : process_(NULL) {
250 }
251 ~RenderWidgetHostTest() {
252 }
253
254 protected:
255 // testing::Test
256 void SetUp() {
257 profile_.reset(new TestingProfile());
258 process_ = new RenderWidgetHostProcess(profile_.get());
259 host_.reset(new MockRenderWidgetHost(process_, 1));
260 view_.reset(new TestView(host_.get()));
261 host_->set_view(view_.get());
262 host_->Init();
263 }
264 void TearDown() {
265 view_.reset();
266 host_.reset();
267 process_ = NULL;
268 profile_.reset();
269
270 // Process all pending tasks to avoid leaks.
271 MessageLoop::current()->RunAllPending();
272 }
273
274 void SendInputEventACK(WebInputEvent::Type type, bool processed) {
275 scoped_ptr<IPC::Message> response(
276 new ViewHostMsg_HandleInputEvent_ACK(0));
277 response->WriteInt(type);
278 response->WriteBool(processed);
279 host_->OnMessageReceived(*response);
280 }
281
282 void SimulateKeyboardEvent(WebInputEvent::Type type) {
283 NativeWebKeyboardEvent key_event;
284 key_event.type = type;
285 key_event.windowsKeyCode = ui::VKEY_L; // non-null made up value.
286 host_->ForwardKeyboardEvent(key_event);
287 }
288
289 void SimulateWheelEvent(float dX, float dY, int modifiers) {
290 WebMouseWheelEvent wheel_event;
291 wheel_event.type = WebInputEvent::MouseWheel;
292 wheel_event.deltaX = dX;
293 wheel_event.deltaY = dY;
294 wheel_event.modifiers = modifiers;
295 host_->ForwardWheelEvent(wheel_event);
296 }
297
298 MessageLoopForUI message_loop_;
299
300 scoped_ptr<TestingProfile> profile_;
301 RenderWidgetHostProcess* process_; // Deleted automatically by the widget.
302 scoped_ptr<MockRenderWidgetHost> host_;
303 scoped_ptr<TestView> view_;
304
305 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostTest);
306 };
307
308 // -----------------------------------------------------------------------------
309
310 TEST_F(RenderWidgetHostTest, Resize) {
311 // The initial bounds is the empty rect, so setting it to the same thing
312 // should do nothing.
313 view_->set_bounds(gfx::Rect());
314 host_->WasResized();
315 EXPECT_FALSE(host_->resize_ack_pending_);
316 EXPECT_EQ(gfx::Size(), host_->in_flight_size_);
317 EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
318
319 // Setting the bounds to a "real" rect should send out the notification.
320 gfx::Rect original_size(0, 0, 100, 100);
321 process_->sink().ClearMessages();
322 view_->set_bounds(original_size);
323 host_->WasResized();
324 EXPECT_TRUE(host_->resize_ack_pending_);
325 EXPECT_EQ(original_size.size(), host_->in_flight_size_);
326 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
327
328 // Send out a update that's not a resize ack. This should not clean the
329 // resize ack pending flag.
330 ViewHostMsg_UpdateRect_Params params;
331 process_->InitUpdateRectParams(&params);
332 host_->OnMsgUpdateRect(params);
333 EXPECT_TRUE(host_->resize_ack_pending_);
334 EXPECT_EQ(original_size.size(), host_->in_flight_size_);
335
336 // Sending out a new notification should NOT send out a new IPC message since
337 // a resize ACK is pending.
338 gfx::Rect second_size(0, 0, 90, 90);
339 process_->sink().ClearMessages();
340 view_->set_bounds(second_size);
341 host_->WasResized();
342 EXPECT_TRUE(host_->resize_ack_pending_);
343 EXPECT_EQ(original_size.size(), host_->in_flight_size_);
344 EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
345
346 // Send a update that's a resize ack, but for the original_size we sent. Since
347 // this isn't the second_size, the message handler should immediately send
348 // a new resize message for the new size to the renderer.
349 process_->sink().ClearMessages();
350 params.flags = ViewHostMsg_UpdateRect_Flags::IS_RESIZE_ACK;
351 params.view_size = original_size.size();
352 host_->OnMsgUpdateRect(params);
353 EXPECT_TRUE(host_->resize_ack_pending_);
354 EXPECT_EQ(second_size.size(), host_->in_flight_size_);
355 ASSERT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
356
357 // Send the resize ack for the latest size.
358 process_->sink().ClearMessages();
359 params.view_size = second_size.size();
360 host_->OnMsgUpdateRect(params);
361 EXPECT_FALSE(host_->resize_ack_pending_);
362 EXPECT_EQ(gfx::Size(), host_->in_flight_size_);
363 ASSERT_FALSE(process_->sink().GetFirstMessageMatching(ViewMsg_Resize::ID));
364
365 // Now clearing the bounds should send out a notification but we shouldn't
366 // expect a resize ack (since the renderer won't ack empty sizes). The message
367 // should contain the new size (0x0) and not the previous one that we skipped
368 process_->sink().ClearMessages();
369 view_->set_bounds(gfx::Rect());
370 host_->WasResized();
371 EXPECT_FALSE(host_->resize_ack_pending_);
372 EXPECT_EQ(gfx::Size(), host_->in_flight_size_);
373 EXPECT_EQ(gfx::Size(), host_->current_size_);
374 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
375
376 // Send a rect that has no area but has either width or height set.
377 // since we do not expect ACK, current_size_ should be updated right away.
378 process_->sink().ClearMessages();
379 view_->set_bounds(gfx::Rect(0, 0, 0, 30));
380 host_->WasResized();
381 EXPECT_FALSE(host_->resize_ack_pending_);
382 EXPECT_EQ(gfx::Size(), host_->in_flight_size_);
383 EXPECT_EQ(gfx::Size(0, 30), host_->current_size_);
384 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
385
386 // Set the same size again. It should not be sent again.
387 process_->sink().ClearMessages();
388 host_->WasResized();
389 EXPECT_FALSE(host_->resize_ack_pending_);
390 EXPECT_EQ(gfx::Size(), host_->in_flight_size_);
391 EXPECT_EQ(gfx::Size(0, 30), host_->current_size_);
392 EXPECT_FALSE(process_->sink().GetFirstMessageMatching(ViewMsg_Resize::ID));
393
394 // A different size should be sent again, however.
395 view_->set_bounds(gfx::Rect(0, 0, 0, 31));
396 host_->WasResized();
397 EXPECT_FALSE(host_->resize_ack_pending_);
398 EXPECT_EQ(gfx::Size(), host_->in_flight_size_);
399 EXPECT_EQ(gfx::Size(0, 31), host_->current_size_);
400 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
401 }
402
403 // Test for crbug.com/25097. If a renderer crashes between a resize and the
404 // corresponding update message, we must be sure to clear the resize ack logic.
405 TEST_F(RenderWidgetHostTest, ResizeThenCrash) {
406 // Setting the bounds to a "real" rect should send out the notification.
407 gfx::Rect original_size(0, 0, 100, 100);
408 view_->set_bounds(original_size);
409 host_->WasResized();
410 EXPECT_TRUE(host_->resize_ack_pending_);
411 EXPECT_EQ(original_size.size(), host_->in_flight_size_);
412 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
413
414 // Simulate a renderer crash before the update message. Ensure all the
415 // resize ack logic is cleared. Must clear the view first so it doesn't get
416 // deleted.
417 host_->set_view(NULL);
418 host_->RendererExited(base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
419 EXPECT_FALSE(host_->resize_ack_pending_);
420 EXPECT_EQ(gfx::Size(), host_->in_flight_size_);
421
422 // Reset the view so we can exit the test cleanly.
423 host_->set_view(view_.get());
424 }
425
426 // Tests setting custom background
427 TEST_F(RenderWidgetHostTest, Background) {
428 #if defined(OS_WIN) || defined(OS_LINUX)
429 scoped_ptr<RenderWidgetHostView> view(
430 RenderWidgetHostView::CreateViewForWidget(host_.get()));
431 host_->set_view(view.get());
432
433 // Create a checkerboard background to test with.
434 gfx::CanvasSkia canvas(4, 4, true);
435 canvas.FillRectInt(SK_ColorBLACK, 0, 0, 2, 2);
436 canvas.FillRectInt(SK_ColorWHITE, 2, 0, 2, 2);
437 canvas.FillRectInt(SK_ColorWHITE, 0, 2, 2, 2);
438 canvas.FillRectInt(SK_ColorBLACK, 2, 2, 2, 2);
439 const SkBitmap& background = canvas.getDevice()->accessBitmap(false);
440
441 // Set the background and make sure we get back a copy.
442 view->SetBackground(background);
443 EXPECT_EQ(4, view->background().width());
444 EXPECT_EQ(4, view->background().height());
445 EXPECT_EQ(background.getSize(), view->background().getSize());
446 EXPECT_TRUE(0 == memcmp(background.getPixels(),
447 view->background().getPixels(),
448 background.getSize()));
449
450 #if defined(OS_WIN)
451 // A message should have been dispatched telling the renderer about the new
452 // background.
453 const IPC::Message* set_background =
454 process_->sink().GetUniqueMessageMatching(ViewMsg_SetBackground::ID);
455 ASSERT_TRUE(set_background);
456 Tuple1<SkBitmap> sent_background;
457 ViewMsg_SetBackground::Read(set_background, &sent_background);
458 EXPECT_EQ(background.getSize(), sent_background.a.getSize());
459 EXPECT_TRUE(0 == memcmp(background.getPixels(),
460 sent_background.a.getPixels(),
461 background.getSize()));
462 #else
463 // TODO(port): When custom backgrounds are implemented for other ports, this
464 // test should work (assuming the background must still be copied into the
465 // renderer -- if not, then maybe the test doesn't apply?).
466 #endif
467
468 #else
469 // TODO(port): Mac does not have gfx::Canvas. Maybe we can just change this
470 // test to use SkCanvas directly?
471 #endif
472
473 // TODO(aa): It would be nice to factor out the painting logic so that we
474 // could test that, but it appears that would mean painting everything twice
475 // since windows HDC structures are opaque.
476 }
477
478 // Tests getting the backing store with the renderer not setting repaint ack
479 // flags.
480 TEST_F(RenderWidgetHostTest, GetBackingStore_NoRepaintAck) {
481 // We don't currently have a backing store, and if the renderer doesn't send
482 // one in time, we should get nothing.
483 process_->set_update_msg_should_reply(false);
484 BackingStore* backing = host_->GetBackingStore(true);
485 EXPECT_FALSE(backing);
486 // The widget host should have sent a request for a repaint, and there should
487 // be no paint ACK.
488 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Repaint::ID));
489 EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(
490 ViewMsg_UpdateRect_ACK::ID));
491
492 // Allowing the renderer to reply in time should give is a backing store.
493 process_->sink().ClearMessages();
494 process_->set_update_msg_should_reply(true);
495 process_->set_update_msg_reply_flags(0);
496 backing = host_->GetBackingStore(true);
497 EXPECT_TRUE(backing);
498 // The widget host should NOT have sent a request for a repaint, since there
499 // was an ACK already pending.
500 EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Repaint::ID));
501 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
502 ViewMsg_UpdateRect_ACK::ID));
503 }
504
505 // Tests getting the backing store with the renderer sending a repaint ack.
506 TEST_F(RenderWidgetHostTest, GetBackingStore_RepaintAck) {
507 // Doing a request request with the update message allowed should work and
508 // the repaint ack should work.
509 process_->set_update_msg_should_reply(true);
510 process_->set_update_msg_reply_flags(
511 ViewHostMsg_UpdateRect_Flags::IS_REPAINT_ACK);
512 BackingStore* backing = host_->GetBackingStore(true);
513 EXPECT_TRUE(backing);
514 // We still should not have sent out a repaint request since the last flags
515 // didn't have the repaint ack set, and the pending flag will still be set.
516 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Repaint::ID));
517 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
518 ViewMsg_UpdateRect_ACK::ID));
519
520 // Asking again for the backing store should just re-use the existing one
521 // and not send any messagse.
522 process_->sink().ClearMessages();
523 backing = host_->GetBackingStore(true);
524 EXPECT_TRUE(backing);
525 EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Repaint::ID));
526 EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(
527 ViewMsg_UpdateRect_ACK::ID));
528 }
529
530 // Test that we don't paint when we're hidden, but we still send the ACK. Most
531 // of the rest of the painting is tested in the GetBackingStore* ones.
532 TEST_F(RenderWidgetHostTest, HiddenPaint) {
533 // Hide the widget, it should have sent out a message to the renderer.
534 EXPECT_FALSE(host_->is_hidden_);
535 host_->WasHidden();
536 EXPECT_TRUE(host_->is_hidden_);
537 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_WasHidden::ID));
538
539 // Send it an update as from the renderer.
540 process_->sink().ClearMessages();
541 ViewHostMsg_UpdateRect_Params params;
542 process_->InitUpdateRectParams(&params);
543 host_->OnMsgUpdateRect(params);
544
545 // It should have sent out the ACK.
546 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
547 ViewMsg_UpdateRect_ACK::ID));
548
549 // Now unhide.
550 process_->sink().ClearMessages();
551 host_->WasRestored();
552 EXPECT_FALSE(host_->is_hidden_);
553
554 // It should have sent out a restored message with a request to paint.
555 const IPC::Message* restored = process_->sink().GetUniqueMessageMatching(
556 ViewMsg_WasRestored::ID);
557 ASSERT_TRUE(restored);
558 Tuple1<bool> needs_repaint;
559 ViewMsg_WasRestored::Read(restored, &needs_repaint);
560 EXPECT_TRUE(needs_repaint.a);
561 }
562
563 TEST_F(RenderWidgetHostTest, PaintAtSize) {
564 const int kPaintAtSizeTag = 42;
565 host_->PaintAtSize(TransportDIB::GetFakeHandleForTest(), kPaintAtSizeTag,
566 gfx::Size(40, 60), gfx::Size(20, 30));
567 EXPECT_TRUE(
568 process_->sink().GetUniqueMessageMatching(ViewMsg_PaintAtSize::ID));
569
570 NotificationRegistrar registrar;
571 MockPaintingObserver observer;
572 registrar.Add(
573 &observer,
574 NotificationType::RENDER_WIDGET_HOST_DID_RECEIVE_PAINT_AT_SIZE_ACK,
575 Source<RenderWidgetHost>(host_.get()));
576
577 host_->OnMsgPaintAtSizeAck(kPaintAtSizeTag, gfx::Size(20, 30));
578 EXPECT_EQ(host_.get(), observer.host());
579 EXPECT_EQ(kPaintAtSizeTag, observer.tag());
580 EXPECT_EQ(20, observer.size().width());
581 EXPECT_EQ(30, observer.size().height());
582 }
583
584 TEST_F(RenderWidgetHostTest, HandleKeyEventsWeSent) {
585 // Simulate a keyboard event.
586 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
587
588 // Make sure we sent the input event to the renderer.
589 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
590 ViewMsg_HandleInputEvent::ID));
591 process_->sink().ClearMessages();
592
593 // Send the simulated response from the renderer back.
594 SendInputEventACK(WebInputEvent::RawKeyDown, false);
595
596 EXPECT_TRUE(host_->unhandled_keyboard_event_called());
597 EXPECT_EQ(WebInputEvent::RawKeyDown, host_->unhandled_keyboard_event_type());
598 }
599
600 TEST_F(RenderWidgetHostTest, IgnoreKeyEventsWeDidntSend) {
601 // Send a simulated, unrequested key response. We should ignore this.
602 SendInputEventACK(WebInputEvent::RawKeyDown, false);
603
604 EXPECT_FALSE(host_->unhandled_keyboard_event_called());
605 }
606
607 TEST_F(RenderWidgetHostTest, IgnoreKeyEventsHandledByRenderer) {
608 // Simulate a keyboard event.
609 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
610
611 // Make sure we sent the input event to the renderer.
612 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
613 ViewMsg_HandleInputEvent::ID));
614 process_->sink().ClearMessages();
615
616 // Send the simulated response from the renderer back.
617 SendInputEventACK(WebInputEvent::RawKeyDown, true);
618 EXPECT_FALSE(host_->unhandled_keyboard_event_called());
619 }
620
621 TEST_F(RenderWidgetHostTest, PreHandleRawKeyDownEvent) {
622 // Simluate the situation that the browser handled the key down event during
623 // pre-handle phrase.
624 host_->set_prehandle_keyboard_event(true);
625 process_->sink().ClearMessages();
626
627 // Simulate a keyboard event.
628 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
629
630 EXPECT_TRUE(host_->prehandle_keyboard_event_called());
631 EXPECT_EQ(WebInputEvent::RawKeyDown, host_->prehandle_keyboard_event_type());
632
633 // Make sure the RawKeyDown event is not sent to the renderer.
634 EXPECT_EQ(0U, process_->sink().message_count());
635
636 // The browser won't pre-handle a Char event.
637 host_->set_prehandle_keyboard_event(false);
638
639 // Forward the Char event.
640 SimulateKeyboardEvent(WebInputEvent::Char);
641
642 // Make sure the Char event is suppressed.
643 EXPECT_EQ(0U, process_->sink().message_count());
644
645 // Forward the KeyUp event.
646 SimulateKeyboardEvent(WebInputEvent::KeyUp);
647
648 // Make sure only KeyUp was sent to the renderer.
649 EXPECT_EQ(1U, process_->sink().message_count());
650 EXPECT_EQ(ViewMsg_HandleInputEvent::ID,
651 process_->sink().GetMessageAt(0)->type());
652 process_->sink().ClearMessages();
653
654 // Send the simulated response from the renderer back.
655 SendInputEventACK(WebInputEvent::KeyUp, false);
656
657 EXPECT_TRUE(host_->unhandled_keyboard_event_called());
658 EXPECT_EQ(WebInputEvent::KeyUp, host_->unhandled_keyboard_event_type());
659 }
660
661 TEST_F(RenderWidgetHostTest, CoalescesWheelEvents) {
662 process_->sink().ClearMessages();
663
664 // Simulate wheel events.
665 SimulateWheelEvent(0, -5, 0); // sent directly
666 SimulateWheelEvent(0, -10, 0); // enqueued
667 SimulateWheelEvent(8, -6, 0); // coalesced into previous event
668 SimulateWheelEvent(9, -7, 1); // enqueued, different modifiers
669
670 // Check that only the first event was sent.
671 EXPECT_EQ(1U, process_->sink().message_count());
672 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
673 ViewMsg_HandleInputEvent::ID));
674 process_->sink().ClearMessages();
675
676 // Check that the ACK sends the second message.
677 SendInputEventACK(WebInputEvent::MouseWheel, true);
678 // The coalesced events can queue up a delayed ack
679 // so that additional input events can be processed before
680 // we turn off coalescing.
681 MessageLoop::current()->RunAllPending();
682 EXPECT_EQ(1U, process_->sink().message_count());
683 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
684 ViewMsg_HandleInputEvent::ID));
685 process_->sink().ClearMessages();
686
687 // One more time.
688 SendInputEventACK(WebInputEvent::MouseWheel, true);
689 MessageLoop::current()->RunAllPending();
690 EXPECT_EQ(1U, process_->sink().message_count());
691 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
692 ViewMsg_HandleInputEvent::ID));
693 process_->sink().ClearMessages();
694
695 // After the final ack, the queue should be empty.
696 SendInputEventACK(WebInputEvent::MouseWheel, true);
697 MessageLoop::current()->RunAllPending();
698 EXPECT_EQ(0U, process_->sink().message_count());
699 }
700
701 // Test that the hang monitor timer expires properly if a new timer is started
702 // while one is in progress (see crbug.com/11007).
703 TEST_F(RenderWidgetHostTest, DontPostponeHangMonitorTimeout) {
704 // Start with a short timeout.
705 host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10));
706
707 // Immediately try to add a long 30 second timeout.
708 EXPECT_FALSE(host_->unresponsive_timer_fired());
709 host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(30000));
710
711 // Wait long enough for first timeout and see if it fired.
712 MessageLoop::current()->PostDelayedTask(FROM_HERE,
713 new MessageLoop::QuitTask(), 10);
714 MessageLoop::current()->Run();
715 EXPECT_TRUE(host_->unresponsive_timer_fired());
716 }
717
718 // Test that the hang monitor timer expires properly if it is started, stopped,
719 // and then started again.
720 TEST_F(RenderWidgetHostTest, StopAndStartHangMonitorTimeout) {
721 // Start with a short timeout, then stop it.
722 host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10));
723 host_->StopHangMonitorTimeout();
724
725 // Start it again to ensure it still works.
726 EXPECT_FALSE(host_->unresponsive_timer_fired());
727 host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10));
728
729 // Wait long enough for first timeout and see if it fired.
730 MessageLoop::current()->PostDelayedTask(FROM_HERE,
731 new MessageLoop::QuitTask(), 10);
732 MessageLoop::current()->Run();
733 EXPECT_TRUE(host_->unresponsive_timer_fired());
734 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698