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

Side by Side Diff: chrome/renderer/render_view_unittest.cc

Issue 3150034: GTTF: move tests that use WebKit from unit_tests to browser_tests... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years, 4 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) 2010 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
7 #include "base/file_util.h"
8 #include "base/keyboard_codes.h"
9 #include "base/shared_memory.h"
10 #include "base/utf_string_conversions.h"
11 #include "chrome/common/content_settings.h"
12 #include "chrome/common/native_web_keyboard_event.h"
13 #include "chrome/common/render_messages.h"
14 #include "chrome/common/render_messages_params.h"
15 #include "chrome/renderer/print_web_view_helper.h"
16 #include "chrome/test/render_view_test.h"
17 #include "gfx/codec/jpeg_codec.h"
18 #include "net/base/net_errors.h"
19 #include "printing/image.h"
20 #include "printing/native_metafile.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
23 #include "third_party/WebKit/WebKit/chromium/public/WebInputElement.h"
24 #include "third_party/WebKit/WebKit/chromium/public/WebString.h"
25 #include "third_party/WebKit/WebKit/chromium/public/WebURLError.h"
26 #include "third_party/WebKit/WebKit/chromium/public/WebView.h"
27 #include "webkit/glue/form_data.h"
28 #include "webkit/glue/form_field.h"
29
30 using WebKit::WebDocument;
31 using WebKit::WebFrame;
32 using WebKit::WebInputElement;
33 using WebKit::WebString;
34 using WebKit::WebTextDirection;
35 using WebKit::WebURLError;
36 using webkit_glue::FormData;
37 using webkit_glue::FormField;
38
39 // Test that we get form state change notifications when input fields change.
40 TEST_F(RenderViewTest, OnNavStateChanged) {
41 // Don't want any delay for form state sync changes. This will still post a
42 // message so updates will get coalesced, but as soon as we spin the message
43 // loop, it will generate an update.
44 view_->set_send_content_state_immediately(true);
45
46 LoadHTML("<input type=\"text\" id=\"elt_text\"></input>");
47
48 // We should NOT have gotten a form state change notification yet.
49 EXPECT_FALSE(render_thread_.sink().GetFirstMessageMatching(
50 ViewHostMsg_UpdateState::ID));
51 render_thread_.sink().ClearMessages();
52
53 // Change the value of the input. We should have gotten an update state
54 // notification. We need to spin the message loop to catch this update.
55 ExecuteJavaScript("document.getElementById('elt_text').value = 'foo';");
56 ProcessPendingMessages();
57 EXPECT_TRUE(render_thread_.sink().GetUniqueMessageMatching(
58 ViewHostMsg_UpdateState::ID));
59 }
60
61 // Test that our IME backend sends a notification message when the input focus
62 // changes.
63 TEST_F(RenderViewTest, OnImeStateChanged) {
64 // Enable our IME backend code.
65 view_->OnSetInputMethodActive(true);
66
67 // Load an HTML page consisting of two input fields.
68 view_->set_send_content_state_immediately(true);
69 LoadHTML("<html>"
70 "<head>"
71 "</head>"
72 "<body>"
73 "<input id=\"test1\" type=\"text\"></input>"
74 "<input id=\"test2\" type=\"password\"></input>"
75 "</body>"
76 "</html>");
77 render_thread_.sink().ClearMessages();
78
79 const int kRepeatCount = 10;
80 for (int i = 0; i < kRepeatCount; i++) {
81 // Move the input focus to the first <input> element, where we should
82 // activate IMEs.
83 ExecuteJavaScript("document.getElementById('test1').focus();");
84 ProcessPendingMessages();
85 render_thread_.sink().ClearMessages();
86
87 // Update the IME status and verify if our IME backend sends an IPC message
88 // to activate IMEs.
89 view_->UpdateInputMethod();
90 const IPC::Message* msg = render_thread_.sink().GetMessageAt(0);
91 EXPECT_TRUE(msg != NULL);
92 EXPECT_EQ(ViewHostMsg_ImeUpdateTextInputState::ID, msg->type());
93 ViewHostMsg_ImeUpdateTextInputState::Param params;
94 ViewHostMsg_ImeUpdateTextInputState::Read(msg, &params);
95 EXPECT_EQ(params.a, WebKit::WebTextInputTypeText);
96 EXPECT_TRUE(params.b.x() > 0 && params.b.y() > 0);
97
98 // Move the input focus to the second <input> element, where we should
99 // de-activate IMEs.
100 ExecuteJavaScript("document.getElementById('test2').focus();");
101 ProcessPendingMessages();
102 render_thread_.sink().ClearMessages();
103
104 // Update the IME status and verify if our IME backend sends an IPC message
105 // to de-activate IMEs.
106 view_->UpdateInputMethod();
107 msg = render_thread_.sink().GetMessageAt(0);
108 EXPECT_TRUE(msg != NULL);
109 EXPECT_EQ(ViewHostMsg_ImeUpdateTextInputState::ID, msg->type());
110 ViewHostMsg_ImeUpdateTextInputState::Read(msg, &params);
111 EXPECT_EQ(params.a, WebKit::WebTextInputTypePassword);
112 }
113 }
114
115 // Test that our IME backend can compose CJK words.
116 // Our IME front-end sends many platform-independent messages to the IME backend
117 // while it composes CJK words. This test sends the minimal messages captured
118 // on my local environment directly to the IME backend to verify if the backend
119 // can compose CJK words without any problems.
120 // This test uses an array of command sets because an IME composotion does not
121 // only depends on IME events, but also depends on window events, e.g. moving
122 // the window focus while composing a CJK text. To handle such complicated
123 // cases, this test should not only call IME-related functions in the
124 // RenderWidget class, but also call some RenderWidget members, e.g.
125 // ExecuteJavaScript(), RenderWidget::OnSetFocus(), etc.
126 TEST_F(RenderViewTest, ImeComposition) {
127 enum ImeCommand {
128 IME_INITIALIZE,
129 IME_SETINPUTMODE,
130 IME_SETFOCUS,
131 IME_SETCOMPOSITION,
132 IME_CONFIRMCOMPOSITION,
133 IME_CANCELCOMPOSITION
134 };
135 struct ImeMessage {
136 ImeCommand command;
137 bool enable;
138 int selection_start;
139 int selection_end;
140 const wchar_t* ime_string;
141 const wchar_t* result;
142 };
143 static const ImeMessage kImeMessages[] = {
144 // Scenario 1: input a Chinese word with Microsoft IME (on Vista).
145 {IME_INITIALIZE, true, 0, 0, NULL, NULL},
146 {IME_SETINPUTMODE, true, 0, 0, NULL, NULL},
147 {IME_SETFOCUS, true, 0, 0, NULL, NULL},
148 {IME_SETCOMPOSITION, false, 1, 1, L"n", L"n"},
149 {IME_SETCOMPOSITION, false, 2, 2, L"ni", L"ni"},
150 {IME_SETCOMPOSITION, false, 3, 3, L"nih", L"nih"},
151 {IME_SETCOMPOSITION, false, 4, 4, L"niha", L"niha"},
152 {IME_SETCOMPOSITION, false, 5, 5, L"nihao", L"nihao"},
153 {IME_SETCOMPOSITION, false, 2, 2, L"\x4F60\x597D", L"\x4F60\x597D"},
154 {IME_CONFIRMCOMPOSITION, false, -1, -1, NULL, L"\x4F60\x597D"},
155 {IME_CANCELCOMPOSITION, false, -1, -1, L"", L"\x4F60\x597D"},
156 // Scenario 2: input a Japanese word with Microsoft IME (on Vista).
157 {IME_INITIALIZE, true, 0, 0, NULL, NULL},
158 {IME_SETINPUTMODE, true, 0, 0, NULL, NULL},
159 {IME_SETFOCUS, true, 0, 0, NULL, NULL},
160 {IME_SETCOMPOSITION, false, 0, 1, L"\xFF4B", L"\xFF4B"},
161 {IME_SETCOMPOSITION, false, 0, 1, L"\x304B", L"\x304B"},
162 {IME_SETCOMPOSITION, false, 0, 2, L"\x304B\xFF4E", L"\x304B\xFF4E"},
163 {IME_SETCOMPOSITION, false, 0, 3, L"\x304B\x3093\xFF4A",
164 L"\x304B\x3093\xFF4A"},
165 {IME_SETCOMPOSITION, false, 0, 3, L"\x304B\x3093\x3058",
166 L"\x304B\x3093\x3058"},
167 {IME_SETCOMPOSITION, false, 0, 2, L"\x611F\x3058", L"\x611F\x3058"},
168 {IME_SETCOMPOSITION, false, 0, 2, L"\x6F22\x5B57", L"\x6F22\x5B57"},
169 {IME_CONFIRMCOMPOSITION, false, -1, -1, NULL, L"\x6F22\x5B57"},
170 {IME_CANCELCOMPOSITION, false, -1, -1, L"", L"\x6F22\x5B57"},
171 // Scenario 3: input a Korean word with Microsot IME (on Vista).
172 {IME_INITIALIZE, true, 0, 0, NULL, NULL},
173 {IME_SETINPUTMODE, true, 0, 0, NULL, NULL},
174 {IME_SETFOCUS, true, 0, 0, NULL, NULL},
175 {IME_SETCOMPOSITION, false, 0, 1, L"\x3147", L"\x3147"},
176 {IME_SETCOMPOSITION, false, 0, 1, L"\xC544", L"\xC544"},
177 {IME_SETCOMPOSITION, false, 0, 1, L"\xC548", L"\xC548"},
178 {IME_CONFIRMCOMPOSITION, false, -1, -1, NULL, L"\xC548"},
179 {IME_SETCOMPOSITION, false, 0, 1, L"\x3134", L"\xC548\x3134"},
180 {IME_SETCOMPOSITION, false, 0, 1, L"\xB140", L"\xC548\xB140"},
181 {IME_SETCOMPOSITION, false, 0, 1, L"\xB155", L"\xC548\xB155"},
182 {IME_CANCELCOMPOSITION, false, -1, -1, L"", L"\xC548"},
183 {IME_SETCOMPOSITION, false, 0, 1, L"\xB155", L"\xC548\xB155"},
184 {IME_CONFIRMCOMPOSITION, false, -1, -1, NULL, L"\xC548\xB155"},
185 };
186
187 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kImeMessages); i++) {
188 const ImeMessage* ime_message = &kImeMessages[i];
189 switch (ime_message->command) {
190 case IME_INITIALIZE:
191 // Load an HTML page consisting of a content-editable <div> element,
192 // and move the input focus to the <div> element, where we can use
193 // IMEs.
194 view_->OnSetInputMethodActive(ime_message->enable);
195 view_->set_send_content_state_immediately(true);
196 LoadHTML("<html>"
197 "<head>"
198 "</head>"
199 "<body>"
200 "<div id=\"test1\" contenteditable=\"true\"></div>"
201 "</body>"
202 "</html>");
203 ExecuteJavaScript("document.getElementById('test1').focus();");
204 break;
205
206 case IME_SETINPUTMODE:
207 // Activate (or deactivate) our IME back-end.
208 view_->OnSetInputMethodActive(ime_message->enable);
209 break;
210
211 case IME_SETFOCUS:
212 // Update the window focus.
213 view_->OnSetFocus(ime_message->enable);
214 break;
215
216 case IME_SETCOMPOSITION:
217 view_->OnImeSetComposition(
218 WideToUTF16Hack(ime_message->ime_string),
219 std::vector<WebKit::WebCompositionUnderline>(),
220 ime_message->selection_start,
221 ime_message->selection_end);
222 break;
223
224 case IME_CONFIRMCOMPOSITION:
225 view_->OnImeConfirmComposition();
226 break;
227
228 case IME_CANCELCOMPOSITION:
229 view_->OnImeSetComposition(string16(),
230 std::vector<WebKit::WebCompositionUnderline>(),
231 0, 0);
232 break;
233 }
234
235 // Update the status of our IME back-end.
236 // TODO(hbono): we should verify messages to be sent from the back-end.
237 view_->UpdateInputMethod();
238 ProcessPendingMessages();
239 render_thread_.sink().ClearMessages();
240
241 if (ime_message->result) {
242 // Retrieve the content of this page and compare it with the expected
243 // result.
244 const int kMaxOutputCharacters = 128;
245 std::wstring output = UTF16ToWideHack(
246 GetMainFrame()->contentAsText(kMaxOutputCharacters));
247 EXPECT_EQ(output, ime_message->result);
248 }
249 }
250 }
251
252 // Test that the RenderView::OnSetTextDirection() function can change the text
253 // direction of the selected input element.
254 TEST_F(RenderViewTest, OnSetTextDirection) {
255 // Load an HTML page consisting of a <textarea> element and a <div> element.
256 // This test changes the text direction of the <textarea> element, and
257 // writes the values of its 'dir' attribute and its 'direction' property to
258 // verify that the text direction is changed.
259 view_->set_send_content_state_immediately(true);
260 LoadHTML("<html>"
261 "<head>"
262 "</head>"
263 "<body>"
264 "<textarea id=\"test\"></textarea>"
265 "<div id=\"result\" contenteditable=\"true\"></div>"
266 "</body>"
267 "</html>");
268 render_thread_.sink().ClearMessages();
269
270 static const struct {
271 WebTextDirection direction;
272 const wchar_t* expected_result;
273 } kTextDirection[] = {
274 { WebKit::WebTextDirectionRightToLeft, L"\x000A" L"rtl,rtl" },
275 { WebKit::WebTextDirectionLeftToRight, L"\x000A" L"ltr,ltr" },
276 };
277 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTextDirection); ++i) {
278 // Set the text direction of the <textarea> element.
279 ExecuteJavaScript("document.getElementById('test').focus();");
280 view_->OnSetTextDirection(kTextDirection[i].direction);
281
282 // Write the values of its DOM 'dir' attribute and its CSS 'direction'
283 // property to the <div> element.
284 ExecuteJavaScript("var result = document.getElementById('result');"
285 "var node = document.getElementById('test');"
286 "var style = getComputedStyle(node, null);"
287 "result.innerText ="
288 " node.getAttribute('dir') + ',' +"
289 " style.getPropertyValue('direction');");
290
291 // Copy the document content to std::wstring and compare with the
292 // expected result.
293 const int kMaxOutputCharacters = 16;
294 std::wstring output = UTF16ToWideHack(
295 GetMainFrame()->contentAsText(kMaxOutputCharacters));
296 EXPECT_EQ(output, kTextDirection[i].expected_result);
297 }
298 }
299
300 // Tests that printing pages work and sending and receiving messages through
301 // that channel all works.
302 TEST_F(RenderViewTest, OnPrintPages) {
303 // Lets simulate a print pages with Hello world.
304 LoadHTML("<body><p>Hello World!</p></body>");
305 view_->OnPrintPages();
306
307 VerifyPageCount(1);
308 VerifyPagesPrinted();
309 }
310
311 // Duplicate of OnPrintPagesTest only using javascript to print.
312 TEST_F(RenderViewTest, PrintWithJavascript) {
313 // HTML contains a call to window.print()
314 LoadHTML("<body>Hello<script>window.print()</script>World</body>");
315
316 VerifyPageCount(1);
317 VerifyPagesPrinted();
318 }
319
320 #if defined(OS_WIN) || defined(OS_MACOSX)
321 // TODO(estade): I don't think this test is worth porting to Linux. We will have
322 // to rip out and replace most of the IPC code if we ever plan to improve
323 // printing, and the comment below by sverrir suggests that it doesn't do much
324 // for us anyway.
325 TEST_F(RenderViewTest, PrintWithIframe) {
326 // Document that populates an iframe.
327 const char html[] =
328 "<html><body>Lorem Ipsum:"
329 "<iframe name=\"sub1\" id=\"sub1\"></iframe><script>"
330 " document.write(frames['sub1'].name);"
331 " frames['sub1'].document.write("
332 " '<p>Cras tempus ante eu felis semper luctus!</p>');"
333 "</script></body></html>";
334
335 LoadHTML(html);
336
337 // Find the frame and set it as the focused one. This should mean that that
338 // the printout should only contain the contents of that frame.
339 WebFrame* sub1_frame =
340 view_->webview()->findFrameByName(WebString::fromUTF8("sub1"));
341 ASSERT_TRUE(sub1_frame);
342 view_->webview()->setFocusedFrame(sub1_frame);
343 ASSERT_NE(view_->webview()->focusedFrame(),
344 view_->webview()->mainFrame());
345
346 // Initiate printing.
347 view_->OnPrintPages();
348
349 // Verify output through MockPrinter.
350 const MockPrinter* printer(render_thread_.printer());
351 ASSERT_EQ(1, printer->GetPrintedPages());
352 const printing::Image& image1(printer->GetPrintedPage(0)->image());
353
354 // TODO(sverrir): Figure out a way to improve this test to actually print
355 // only the content of the iframe. Currently image1 will contain the full
356 // page.
357 EXPECT_NE(0, image1.size().width());
358 EXPECT_NE(0, image1.size().height());
359 }
360 #endif
361
362 // Tests if we can print a page and verify its results.
363 // This test prints HTML pages into a pseudo printer and check their outputs,
364 // i.e. a simplified version of the PrintingLayoutTextTest UI test.
365 namespace {
366 // Test cases used in this test.
367 struct TestPageData {
368 const char* page;
369 size_t printed_pages;
370 int width;
371 int height;
372 const char* checksum;
373 const wchar_t* file;
374 };
375
376 const TestPageData kTestPages[] = {
377 {"<html>"
378 "<head>"
379 "<meta"
380 " http-equiv=\"Content-Type\""
381 " content=\"text/html; charset=utf-8\"/>"
382 "<title>Test 1</title>"
383 "</head>"
384 "<body style=\"background-color: white;\">"
385 "<p style=\"font-family: arial;\">Hello World!</p>"
386 "</body>",
387 #if defined(OS_MACOSX)
388 // Mac printing code compensates for the WebKit scale factor while generating
389 // the metafile, so we expect smaller pages.
390 1, 612, 792,
391 #else
392 1, 764, 972,
393 #endif
394 NULL,
395 NULL,
396 },
397 };
398 } // namespace
399
400 // TODO(estade): need to port MockPrinter to get this on Linux. This involves
401 // hooking up Cairo to read a pdf stream, or accessing the cairo surface in the
402 // metafile directly.
403 #if defined(OS_WIN) || defined(OS_MACOSX)
404 TEST_F(RenderViewTest, PrintLayoutTest) {
405 bool baseline = false;
406
407 EXPECT_TRUE(render_thread_.printer() != NULL);
408 for (size_t i = 0; i < arraysize(kTestPages); ++i) {
409 // Load an HTML page and print it.
410 LoadHTML(kTestPages[i].page);
411 view_->OnPrintPages();
412
413 // MockRenderThread::Send() just calls MockRenderThread::OnMsgReceived().
414 // So, all IPC messages sent in the above RenderView::OnPrintPages() call
415 // has been handled by the MockPrinter object, i.e. this printing job
416 // has been already finished.
417 // So, we can start checking the output pages of this printing job.
418 // Retrieve the number of pages actually printed.
419 size_t pages = render_thread_.printer()->GetPrintedPages();
420 EXPECT_EQ(kTestPages[i].printed_pages, pages);
421
422 // Retrieve the width and height of the output page.
423 int width = render_thread_.printer()->GetWidth(0);
424 int height = render_thread_.printer()->GetHeight(0);
425
426 // Check with margin for error. This has been failing with a one pixel
427 // offset on our buildbot.
428 const int kErrorMargin = 5; // 5%
429 EXPECT_GT(kTestPages[i].width * (100 + kErrorMargin) / 100, width);
430 EXPECT_LT(kTestPages[i].width * (100 - kErrorMargin) / 100, width);
431 EXPECT_GT(kTestPages[i].height * (100 + kErrorMargin) / 100, height);
432 EXPECT_LT(kTestPages[i].height* (100 - kErrorMargin) / 100, height);
433
434 // Retrieve the checksum of the bitmap data from the pseudo printer and
435 // compare it with the expected result.
436 std::string bitmap_actual;
437 EXPECT_TRUE(render_thread_.printer()->GetBitmapChecksum(0, &bitmap_actual));
438 if (kTestPages[i].checksum)
439 EXPECT_EQ(kTestPages[i].checksum, bitmap_actual);
440
441 if (baseline) {
442 // Save the source data and the bitmap data into temporary files to
443 // create base-line results.
444 FilePath source_path;
445 file_util::CreateTemporaryFile(&source_path);
446 render_thread_.printer()->SaveSource(0, source_path);
447
448 FilePath bitmap_path;
449 file_util::CreateTemporaryFile(&bitmap_path);
450 render_thread_.printer()->SaveBitmap(0, bitmap_path);
451 }
452 }
453 }
454 #endif
455
456 // Print page as bitmap test.
457 TEST_F(RenderViewTest, OnPrintPageAsBitmap) {
458 // Lets simulate a print pages with Hello world.
459 LoadHTML("<body><p>Hello world!</p></body>");
460
461 // Grab the printer settings from the printer.
462 ViewMsg_Print_Params print_settings;
463 MockPrinter* printer(render_thread_.printer());
464 printer->GetDefaultPrintSettings(&print_settings);
465 ViewMsg_PrintPage_Params page_params = ViewMsg_PrintPage_Params();
466 page_params.params = print_settings;
467 page_params.page_number = 0;
468
469 // Fetch the image data from the web frame.
470 std::vector<unsigned char> data;
471 view_->print_helper()->PrintPageAsJPEG(page_params,
472 view_->webview()->mainFrame(),
473 1.0f,
474 &data);
475 std::vector<unsigned char> decoded;
476 int w, h;
477 EXPECT_TRUE(gfx::JPEGCodec::Decode(&data[0], data.size(),
478 gfx::JPEGCodec::FORMAT_RGBA,
479 &decoded, &w, &h));
480
481 // Check if it's not 100% white.
482 bool is_white = true;
483 for (int y = 0; y < h; y++) {
484 for (int x = 0; x < w; x++) {
485 unsigned char* px = &decoded[(y * w + x) * 4];
486 if (px[0] != 0xFF && px[1] != 0xFF && px[2] != 0xFF) {
487 is_white = false;
488 break;
489 }
490 }
491 }
492 ASSERT_TRUE(!is_white);
493 }
494
495 // Test that we can receive correct DOM events when we send input events
496 // through the RenderWidget::OnHandleInputEvent() function.
497 // Crashy, http://crbug.com/52643.
498 TEST_F(RenderViewTest, DISABLED_OnHandleKeyboardEvent) {
499 #if defined(OS_WIN) || defined(OS_LINUX)
500 // Load an HTML page consisting of one <input> element and three
501 // contentediable <div> elements.
502 // The <input> element is used for sending keyboard events, and the <div>
503 // elements are used for writing DOM events in the following format:
504 // "<keyCode>,<shiftKey>,<controlKey>,<altKey>".
505 // TODO(hbono): <http://crbug.com/2215> Our WebKit port set |ev.metaKey| to
506 // true when pressing an alt key, i.e. the |ev.metaKey| value is not
507 // trustworthy. We will check the |ev.metaKey| value when this issue is fixed.
508 view_->set_send_content_state_immediately(true);
509 LoadHTML("<html>"
510 "<head>"
511 "<title></title>"
512 "<script type='text/javascript' language='javascript'>"
513 "function OnKeyEvent(ev) {"
514 " var result = document.getElementById(ev.type);"
515 " result.innerText ="
516 " (ev.which || ev.keyCode) + ',' +"
517 " ev.shiftKey + ',' +"
518 " ev.ctrlKey + ',' +"
519 " ev.altKey;"
520 " return true;"
521 "}"
522 "</script>"
523 "</head>"
524 "<body>"
525 "<input id='test' type='text'"
526 " onkeydown='return OnKeyEvent(event);'"
527 " onkeypress='return OnKeyEvent(event);'"
528 " onkeyup='return OnKeyEvent(event);'>"
529 "</input>"
530 "<div id='keydown' contenteditable='true'>"
531 "</div>"
532 "<div id='keypress' contenteditable='true'>"
533 "</div>"
534 "<div id='keyup' contenteditable='true'>"
535 "</div>"
536 "</body>"
537 "</html>");
538 ExecuteJavaScript("document.getElementById('test').focus();");
539 render_thread_.sink().ClearMessages();
540
541 static const MockKeyboard::Layout kLayouts[] = {
542 #if defined(OS_WIN)
543 // Since we ignore the mock keyboard layout on Linux and instead just use
544 // the screen's keyboard layout, these trivially pass. They are commented
545 // out to avoid the illusion that they work.
546 MockKeyboard::LAYOUT_ARABIC,
547 MockKeyboard::LAYOUT_CANADIAN_FRENCH,
548 MockKeyboard::LAYOUT_FRENCH,
549 MockKeyboard::LAYOUT_HEBREW,
550 MockKeyboard::LAYOUT_RUSSIAN,
551 #endif
552 MockKeyboard::LAYOUT_UNITED_STATES,
553 };
554
555 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kLayouts); ++i) {
556 // For each key code, we send three keyboard events.
557 // * we press only the key;
558 // * we press the key and a left-shift key, and;
559 // * we press the key and a right-alt (AltGr) key.
560 // For each modifiers, we need a string used for formatting its expected
561 // result. (See the above comment for its format.)
562 static const struct {
563 MockKeyboard::Modifiers modifiers;
564 const char* expected_result;
565 } kModifierData[] = {
566 {MockKeyboard::NONE, "false,false,false"},
567 {MockKeyboard::LEFT_SHIFT, "true,false,false"},
568 #if defined(OS_WIN)
569 {MockKeyboard::RIGHT_ALT, "false,false,true"},
570 #endif
571 };
572
573 MockKeyboard::Layout layout = kLayouts[i];
574 for (size_t j = 0; j < ARRAYSIZE_UNSAFE(kModifierData); ++j) {
575 // Virtual key codes used for this test.
576 static const int kKeyCodes[] = {
577 '0', '1', '2', '3', '4', '5', '6', '7',
578 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
579 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
580 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
581 'W', 'X', 'Y', 'Z',
582 base::VKEY_OEM_1,
583 base::VKEY_OEM_PLUS,
584 base::VKEY_OEM_COMMA,
585 base::VKEY_OEM_MINUS,
586 base::VKEY_OEM_PERIOD,
587 base::VKEY_OEM_2,
588 base::VKEY_OEM_3,
589 base::VKEY_OEM_4,
590 base::VKEY_OEM_5,
591 base::VKEY_OEM_6,
592 base::VKEY_OEM_7,
593 #if defined(OS_WIN)
594 // Not sure how to handle this key on Linux.
595 base::VKEY_OEM_8,
596 #endif
597 };
598
599 MockKeyboard::Modifiers modifiers = kModifierData[j].modifiers;
600 for (size_t k = 0; k < ARRAYSIZE_UNSAFE(kKeyCodes); ++k) {
601 // Send a keyboard event to the RenderView object.
602 // We should test a keyboard event only when the given keyboard-layout
603 // driver is installed in a PC and the driver can assign a Unicode
604 // charcter for the given tuple (key-code and modifiers).
605 int key_code = kKeyCodes[k];
606 std::wstring char_code;
607 if (SendKeyEvent(layout, key_code, modifiers, &char_code) < 0)
608 continue;
609
610 // Create an expected result from the virtual-key code, the character
611 // code, and the modifier-key status.
612 // We format a string that emulates a DOM-event string produced hy
613 // our JavaScript function. (See the above comment for the format.)
614 static char expected_result[1024];
615 expected_result[0] = NULL;
616 sprintf(&expected_result[0],
617 "\n" // texts in the <input> element
618 "%d,%s\n" // texts in the first <div> element
619 "%d,%s\n" // texts in the second <div> element
620 "%d,%s", // texts in the third <div> element
621 key_code, kModifierData[j].expected_result,
622 char_code[0], kModifierData[j].expected_result,
623 key_code, kModifierData[j].expected_result);
624
625 // Retrieve the text in the test page and compare it with the expected
626 // text created from a virtual-key code, a character code, and the
627 // modifier-key status.
628 const int kMaxOutputCharacters = 1024;
629 std::string output = UTF16ToUTF8(
630 GetMainFrame()->contentAsText(kMaxOutputCharacters));
631 EXPECT_EQ(expected_result, output);
632 }
633 }
634 }
635 #else
636 NOTIMPLEMENTED();
637 #endif
638 }
639
640 // Test that our EditorClientImpl class can insert characters when we send
641 // keyboard events through the RenderWidget::OnHandleInputEvent() function.
642 // This test is for preventing regressions caused only when we use non-US
643 // keyboards, such as Issue 10846.
644 TEST_F(RenderViewTest, InsertCharacters) {
645 #if defined(OS_WIN) || defined(OS_LINUX)
646 static const struct {
647 MockKeyboard::Layout layout;
648 const wchar_t* expected_result;
649 } kLayouts[] = {
650 #if 0
651 // Disabled these keyboard layouts because buildbots do not have their
652 // keyboard-layout drivers installed.
653 {MockKeyboard::LAYOUT_ARABIC,
654 L"\x0030\x0031\x0032\x0033\x0034\x0035\x0036\x0037"
655 L"\x0038\x0039\x0634\x0624\x064a\x062b\x0628\x0644"
656 L"\x0627\x0647\x062a\x0646\x0645\x0629\x0649\x062e"
657 L"\x062d\x0636\x0642\x0633\x0641\x0639\x0631\x0635"
658 L"\x0621\x063a\x0626\x0643\x003d\x0648\x002d\x0632"
659 L"\x0638\x0630\x062c\x005c\x062f\x0637\x0028\x0021"
660 L"\x0040\x0023\x0024\x0025\x005e\x0026\x002a\x0029"
661 L"\x0650\x007d\x005d\x064f\x005b\x0623\x00f7\x0640"
662 L"\x060c\x002f\x2019\x0622\x00d7\x061b\x064e\x064c"
663 L"\x064d\x2018\x007b\x064b\x0652\x0625\x007e\x003a"
664 L"\x002b\x002c\x005f\x002e\x061f\x0651\x003c\x007c"
665 L"\x003e\x0022\x0030\x0031\x0032\x0033\x0034\x0035"
666 L"\x0036\x0037\x0038\x0039\x0634\x0624\x064a\x062b"
667 L"\x0628\x0644\x0627\x0647\x062a\x0646\x0645\x0629"
668 L"\x0649\x062e\x062d\x0636\x0642\x0633\x0641\x0639"
669 L"\x0631\x0635\x0621\x063a\x0626\x0643\x003d\x0648"
670 L"\x002d\x0632\x0638\x0630\x062c\x005c\x062f\x0637"
671 },
672 {MockKeyboard::LAYOUT_HEBREW,
673 L"\x0030\x0031\x0032\x0033\x0034\x0035\x0036\x0037"
674 L"\x0038\x0039\x05e9\x05e0\x05d1\x05d2\x05e7\x05db"
675 L"\x05e2\x05d9\x05df\x05d7\x05dc\x05da\x05e6\x05de"
676 L"\x05dd\x05e4\x002f\x05e8\x05d3\x05d0\x05d5\x05d4"
677 L"\x0027\x05e1\x05d8\x05d6\x05e3\x003d\x05ea\x002d"
678 L"\x05e5\x002e\x003b\x005d\x005c\x005b\x002c\x0028"
679 L"\x0021\x0040\x0023\x0024\x0025\x005e\x0026\x002a"
680 L"\x0029\x0041\x0042\x0043\x0044\x0045\x0046\x0047"
681 L"\x0048\x0049\x004a\x004b\x004c\x004d\x004e\x004f"
682 L"\x0050\x0051\x0052\x0053\x0054\x0055\x0056\x0057"
683 L"\x0058\x0059\x005a\x003a\x002b\x003e\x005f\x003c"
684 L"\x003f\x007e\x007d\x007c\x007b\x0022\x0030\x0031"
685 L"\x0032\x0033\x0034\x0035\x0036\x0037\x0038\x0039"
686 L"\x05e9\x05e0\x05d1\x05d2\x05e7\x05db\x05e2\x05d9"
687 L"\x05df\x05d7\x05dc\x05da\x05e6\x05de\x05dd\x05e4"
688 L"\x002f\x05e8\x05d3\x05d0\x05d5\x05d4\x0027\x05e1"
689 L"\x05d8\x05d6\x05e3\x003d\x05ea\x002d\x05e5\x002e"
690 L"\x003b\x005d\x005c\x005b\x002c"
691 },
692 #endif
693 #if defined(OS_WIN)
694 // On Linux, the only way to test alternate keyboard layouts is to change
695 // the keyboard layout of the whole screen. I'm worried about the side
696 // effects this may have on the buildbots.
697 {MockKeyboard::LAYOUT_CANADIAN_FRENCH,
698 L"\x0030\x0031\x0032\x0033\x0034\x0035\x0036\x0037"
699 L"\x0038\x0039\x0061\x0062\x0063\x0064\x0065\x0066"
700 L"\x0067\x0068\x0069\x006a\x006b\x006c\x006d\x006e"
701 L"\x006f\x0070\x0071\x0072\x0073\x0074\x0075\x0076"
702 L"\x0077\x0078\x0079\x007a\x003b\x003d\x002c\x002d"
703 L"\x002e\x00e9\x003c\x0029\x0021\x0022\x002f\x0024"
704 L"\x0025\x003f\x0026\x002a\x0028\x0041\x0042\x0043"
705 L"\x0044\x0045\x0046\x0047\x0048\x0049\x004a\x004b"
706 L"\x004c\x004d\x004e\x004f\x0050\x0051\x0052\x0053"
707 L"\x0054\x0055\x0056\x0057\x0058\x0059\x005a\x003a"
708 L"\x002b\x0027\x005f\x002e\x00c9\x003e\x0030\x0031"
709 L"\x0032\x0033\x0034\x0035\x0036\x0037\x0038\x0039"
710 L"\x0061\x0062\x0063\x0064\x0065\x0066\x0067\x0068"
711 L"\x0069\x006a\x006b\x006c\x006d\x006e\x006f\x0070"
712 L"\x0071\x0072\x0073\x0074\x0075\x0076\x0077\x0078"
713 L"\x0079\x007a\x003b\x003d\x002c\x002d\x002e\x00e9"
714 L"\x003c"
715 },
716 {MockKeyboard::LAYOUT_FRENCH,
717 L"\x00e0\x0026\x00e9\x0022\x0027\x0028\x002d\x00e8"
718 L"\x005f\x00e7\x0061\x0062\x0063\x0064\x0065\x0066"
719 L"\x0067\x0068\x0069\x006a\x006b\x006c\x006d\x006e"
720 L"\x006f\x0070\x0071\x0072\x0073\x0074\x0075\x0076"
721 L"\x0077\x0078\x0079\x007a\x0024\x003d\x002c\x003b"
722 L"\x003a\x00f9\x0029\x002a\x0021\x0030\x0031\x0032"
723 L"\x0033\x0034\x0035\x0036\x0037\x0038\x0039\x0041"
724 L"\x0042\x0043\x0044\x0045\x0046\x0047\x0048\x0049"
725 L"\x004a\x004b\x004c\x004d\x004e\x004f\x0050\x0051"
726 L"\x0052\x0053\x0054\x0055\x0056\x0057\x0058\x0059"
727 L"\x005a\x00a3\x002b\x003f\x002e\x002f\x0025\x00b0"
728 L"\x00b5\x00e0\x0026\x00e9\x0022\x0027\x0028\x002d"
729 L"\x00e8\x005f\x00e7\x0061\x0062\x0063\x0064\x0065"
730 L"\x0066\x0067\x0068\x0069\x006a\x006b\x006c\x006d"
731 L"\x006e\x006f\x0070\x0071\x0072\x0073\x0074\x0075"
732 L"\x0076\x0077\x0078\x0079\x007a\x0024\x003d\x002c"
733 L"\x003b\x003a\x00f9\x0029\x002a\x0021"
734 },
735 {MockKeyboard::LAYOUT_RUSSIAN,
736 L"\x0030\x0031\x0032\x0033\x0034\x0035\x0036\x0037"
737 L"\x0038\x0039\x0444\x0438\x0441\x0432\x0443\x0430"
738 L"\x043f\x0440\x0448\x043e\x043b\x0434\x044c\x0442"
739 L"\x0449\x0437\x0439\x043a\x044b\x0435\x0433\x043c"
740 L"\x0446\x0447\x043d\x044f\x0436\x003d\x0431\x002d"
741 L"\x044e\x002e\x0451\x0445\x005c\x044a\x044d\x0029"
742 L"\x0021\x0022\x2116\x003b\x0025\x003a\x003f\x002a"
743 L"\x0028\x0424\x0418\x0421\x0412\x0423\x0410\x041f"
744 L"\x0420\x0428\x041e\x041b\x0414\x042c\x0422\x0429"
745 L"\x0417\x0419\x041a\x042b\x0415\x0413\x041c\x0426"
746 L"\x0427\x041d\x042f\x0416\x002b\x0411\x005f\x042e"
747 L"\x002c\x0401\x0425\x002f\x042a\x042d\x0030\x0031"
748 L"\x0032\x0033\x0034\x0035\x0036\x0037\x0038\x0039"
749 L"\x0444\x0438\x0441\x0432\x0443\x0430\x043f\x0440"
750 L"\x0448\x043e\x043b\x0434\x044c\x0442\x0449\x0437"
751 L"\x0439\x043a\x044b\x0435\x0433\x043c\x0446\x0447"
752 L"\x043d\x044f\x0436\x003d\x0431\x002d\x044e\x002e"
753 L"\x0451\x0445\x005c\x044a\x044d"
754 },
755 #endif // defined(OS_WIN)
756 {MockKeyboard::LAYOUT_UNITED_STATES,
757 L"\x0030\x0031\x0032\x0033\x0034\x0035\x0036\x0037"
758 L"\x0038\x0039\x0061\x0062\x0063\x0064\x0065\x0066"
759 L"\x0067\x0068\x0069\x006a\x006b\x006c\x006d\x006e"
760 L"\x006f\x0070\x0071\x0072\x0073\x0074\x0075\x0076"
761 L"\x0077\x0078\x0079\x007a\x003b\x003d\x002c\x002d"
762 L"\x002e\x002f\x0060\x005b\x005c\x005d\x0027\x0029"
763 L"\x0021\x0040\x0023\x0024\x0025\x005e\x0026\x002a"
764 L"\x0028\x0041\x0042\x0043\x0044\x0045\x0046\x0047"
765 L"\x0048\x0049\x004a\x004b\x004c\x004d\x004e\x004f"
766 L"\x0050\x0051\x0052\x0053\x0054\x0055\x0056\x0057"
767 L"\x0058\x0059\x005a\x003a\x002b\x003c\x005f\x003e"
768 L"\x003f\x007e\x007b\x007c\x007d\x0022"
769 #if defined(OS_WIN)
770 // This is ifdefed out for Linux to correspond to the fact that we don't
771 // test alt+keystroke for now.
772 L"\x0030\x0031\x0032\x0033\x0034\x0035\x0036\x0037"
773 L"\x0038\x0039\x0061\x0062\x0063\x0064\x0065\x0066"
774 L"\x0067\x0068\x0069\x006a\x006b\x006c\x006d\x006e"
775 L"\x006f\x0070\x0071\x0072\x0073\x0074\x0075\x0076"
776 L"\x0077\x0078\x0079\x007a\x003b\x003d\x002c\x002d"
777 L"\x002e\x002f\x0060\x005b\x005c\x005d\x0027"
778 #endif
779 },
780 };
781
782 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kLayouts); ++i) {
783 // Load an HTML page consisting of one <div> element.
784 // This <div> element is used by the EditorClientImpl class to insert
785 // characters received through the RenderWidget::OnHandleInputEvent()
786 // function.
787 view_->set_send_content_state_immediately(true);
788 LoadHTML("<html>"
789 "<head>"
790 "<title></title>"
791 "</head>"
792 "<body>"
793 "<div id='test' contenteditable='true'>"
794 "</div>"
795 "</body>"
796 "</html>");
797 ExecuteJavaScript("document.getElementById('test').focus();");
798 render_thread_.sink().ClearMessages();
799
800 // For each key code, we send three keyboard events.
801 // * Pressing only the key;
802 // * Pressing the key and a left-shift key, and;
803 // * Pressing the key and a right-alt (AltGr) key.
804 static const MockKeyboard::Modifiers kModifiers[] = {
805 MockKeyboard::NONE,
806 MockKeyboard::LEFT_SHIFT,
807 #if defined(OS_WIN)
808 MockKeyboard::RIGHT_ALT,
809 #endif
810 };
811
812 MockKeyboard::Layout layout = kLayouts[i].layout;
813 for (size_t j = 0; j < ARRAYSIZE_UNSAFE(kModifiers); ++j) {
814 // Virtual key codes used for this test.
815 static const int kKeyCodes[] = {
816 '0', '1', '2', '3', '4', '5', '6', '7',
817 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
818 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
819 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
820 'W', 'X', 'Y', 'Z',
821 base::VKEY_OEM_1,
822 base::VKEY_OEM_PLUS,
823 base::VKEY_OEM_COMMA,
824 base::VKEY_OEM_MINUS,
825 base::VKEY_OEM_PERIOD,
826 base::VKEY_OEM_2,
827 base::VKEY_OEM_3,
828 base::VKEY_OEM_4,
829 base::VKEY_OEM_5,
830 base::VKEY_OEM_6,
831 base::VKEY_OEM_7,
832 #if defined(OS_WIN)
833 // Unclear how to handle this on Linux.
834 base::VKEY_OEM_8,
835 #endif
836 };
837
838 MockKeyboard::Modifiers modifiers = kModifiers[j];
839 for (size_t k = 0; k < ARRAYSIZE_UNSAFE(kKeyCodes); ++k) {
840 // Send a keyboard event to the RenderView object.
841 // We should test a keyboard event only when the given keyboard-layout
842 // driver is installed in a PC and the driver can assign a Unicode
843 // charcter for the given tuple (layout, key-code, and modifiers).
844 int key_code = kKeyCodes[k];
845 std::wstring char_code;
846 if (SendKeyEvent(layout, key_code, modifiers, &char_code) < 0)
847 continue;
848 }
849 }
850
851 // Retrieve the text in the test page and compare it with the expected
852 // text created from a virtual-key code, a character code, and the
853 // modifier-key status.
854 const int kMaxOutputCharacters = 4096;
855 std::wstring output = UTF16ToWideHack(
856 GetMainFrame()->contentAsText(kMaxOutputCharacters));
857 EXPECT_EQ(kLayouts[i].expected_result, output);
858 }
859 #else
860 NOTIMPLEMENTED();
861 #endif
862 }
863
864 TEST_F(RenderViewTest, DidFailProvisionalLoadWithErrorForError) {
865 GetMainFrame()->enableViewSourceMode(true);
866 WebURLError error;
867 error.domain.fromUTF8("test_domain");
868 error.reason = net::ERR_FILE_NOT_FOUND;
869 error.unreachableURL = GURL("http://foo");
870 WebFrame* web_frame = GetMainFrame();
871 // An error occurred.
872 view_->didFailProvisionalLoad(web_frame, error);
873 // Frame should exit view-source mode.
874 EXPECT_FALSE(web_frame->isViewSourceModeEnabled());
875 }
876
877 TEST_F(RenderViewTest, DidFailProvisionalLoadWithErrorForCancellation) {
878 GetMainFrame()->enableViewSourceMode(true);
879 WebURLError error;
880 error.domain.fromUTF8("test_domain");
881 error.reason = net::ERR_ABORTED;
882 error.unreachableURL = GURL("http://foo");
883 WebFrame* web_frame = GetMainFrame();
884 // A cancellation occurred.
885 view_->didFailProvisionalLoad(web_frame, error);
886 // Frame should stay in view-source mode.
887 EXPECT_TRUE(web_frame->isViewSourceModeEnabled());
888 }
889
890 // Regression test for http://crbug.com/35011
891 TEST_F(RenderViewTest, JSBlockSentAfterPageLoad) {
892 // 1. Load page with JS.
893 std::string html = "<html>"
894 "<head>"
895 "<script>document.createElement('div');</script>"
896 "</head>"
897 "<body>"
898 "</body>"
899 "</html>";
900 render_thread_.sink().ClearMessages();
901 LoadHTML(html.c_str());
902
903 // 2. Block JavaScript.
904 ContentSettings settings;
905 for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i)
906 settings.settings[i] = CONTENT_SETTING_ALLOW;
907 settings.settings[CONTENT_SETTINGS_TYPE_JAVASCRIPT] = CONTENT_SETTING_BLOCK;
908 view_->SetContentSettings(settings);
909
910 // Make sure no pending messages are in the queue.
911 ProcessPendingMessages();
912 render_thread_.sink().ClearMessages();
913
914 // 3. Reload page.
915 ViewMsg_Navigate_Params params = { 0 };
916 std::string url_str = "data:text/html;charset=utf-8,";
917 url_str.append(html);
918 GURL url(url_str);
919 params.url = url;
920 params.navigation_type = ViewMsg_Navigate_Params::RELOAD;
921 view_->OnNavigate(params);
922 ProcessPendingMessages();
923
924 // 4. Verify that the notification that javascript was blocked is sent after
925 // the navigation notifiction is sent.
926 int navigation_index = -1;
927 int block_index = -1;
928 for (size_t i = 0; i < render_thread_.sink().message_count(); ++i) {
929 const IPC::Message* msg = render_thread_.sink().GetMessageAt(i);
930 if (msg->type() == ViewHostMsg_FrameNavigate::ID)
931 navigation_index = i;
932 if (msg->type() == ViewHostMsg_ContentBlocked::ID)
933 block_index = i;
934 }
935 EXPECT_NE(-1, navigation_index);
936 EXPECT_NE(-1, block_index);
937 EXPECT_LT(navigation_index, block_index);
938 }
939
940 // Regression test for http://crbug.com/41562
941 TEST_F(RenderViewTest, UpdateTargetURLWithInvalidURL) {
942 const GURL invalid_gurl("http://");
943 view_->setMouseOverURL(WebKit::WebURL(invalid_gurl));
944 EXPECT_EQ(invalid_gurl, view_->target_url_);
945 }
946
947 TEST_F(RenderViewTest, SendForms) {
948 // Don't want any delay for form state sync changes. This will still post a
949 // message so updates will get coalesced, but as soon as we spin the message
950 // loop, it will generate an update.
951 view_->set_send_content_state_immediately(true);
952
953 LoadHTML("<form method=\"POST\">"
954 " <input type=\"text\" id=\"firstname\"/>"
955 " <input type=\"text\" id=\"middlename\" autoComplete=\"off\"/>"
956 " <input type=\"hidden\" id=\"lastname\"/>"
957 "</form>");
958
959 // Verify that "FormsSeen" sends the expected number of fields.
960 ProcessPendingMessages();
961 const IPC::Message* message = render_thread_.sink().GetUniqueMessageMatching(
962 ViewHostMsg_FormsSeen::ID);
963 ASSERT_NE(static_cast<IPC::Message*>(NULL), message);
964 ViewHostMsg_FormsSeen::Param params;
965 ViewHostMsg_FormsSeen::Read(message, &params);
966 const std::vector<FormData>& forms = params.a;
967 ASSERT_EQ(1UL, forms.size());
968 ASSERT_EQ(3UL, forms[0].fields.size());
969 EXPECT_TRUE(forms[0].fields[0].StrictlyEqualsHack(
970 FormField(string16(),
971 ASCIIToUTF16("firstname"),
972 string16(),
973 ASCIIToUTF16("text"),
974 20))) << forms[0].fields[0];
975 EXPECT_TRUE(forms[0].fields[1].StrictlyEqualsHack(
976 FormField(string16(),
977 ASCIIToUTF16("middlename"),
978 string16(),
979 ASCIIToUTF16("text"),
980 20))) << forms[0].fields[1];
981 EXPECT_TRUE(forms[0].fields[2].StrictlyEqualsHack(
982 FormField(string16(),
983 ASCIIToUTF16("lastname"),
984 string16(),
985 ASCIIToUTF16("hidden"),
986 0))) << forms[0].fields[2];
987
988 // Verify that |didAcceptAutoFillSuggestion()| sends the expected number of
989 // fields.
990 WebFrame* web_frame = GetMainFrame();
991 WebDocument document = web_frame->document();
992 WebInputElement firstname =
993 document.getElementById("firstname").to<WebInputElement>();
994
995 // Accept suggestion that contains a label. Labeled items indicate AutoFill
996 // as opposed to Autocomplete. We're testing this distinction below with
997 // the |ViewHostMsg_FillAutoFillFormData::ID| message.
998 view_->didAcceptAutoFillSuggestion(firstname,
999 WebKit::WebString::fromUTF8("Johnny"),
1000 WebKit::WebString::fromUTF8("Home"),
1001 1,
1002 -1);
1003
1004 ProcessPendingMessages();
1005 const IPC::Message* message2 = render_thread_.sink().GetUniqueMessageMatching(
1006 ViewHostMsg_FillAutoFillFormData::ID);
1007 ASSERT_NE(static_cast<IPC::Message*>(NULL), message2);
1008 ViewHostMsg_FillAutoFillFormData::Param params2;
1009 ViewHostMsg_FillAutoFillFormData::Read(message2, &params2);
1010 const FormData& form2 = params2.b;
1011 ASSERT_EQ(3UL, form2.fields.size());
1012 EXPECT_TRUE(form2.fields[0].StrictlyEqualsHack(
1013 FormField(string16(),
1014 ASCIIToUTF16("firstname"),
1015 string16(),
1016 ASCIIToUTF16("text"),
1017 20))) << form2.fields[0];
1018 EXPECT_TRUE(form2.fields[1].StrictlyEqualsHack(
1019 FormField(string16(),
1020 ASCIIToUTF16("middlename"),
1021 string16(),
1022 ASCIIToUTF16("text"),
1023 20))) << form2.fields[1];
1024 EXPECT_TRUE(form2.fields[2].StrictlyEqualsHack(
1025 FormField(string16(),
1026 ASCIIToUTF16("lastname"),
1027 string16(),
1028 ASCIIToUTF16("hidden"),
1029 0))) << form2.fields[2];
1030 }
1031
1032 TEST_F(RenderViewTest, FillFormElement) {
1033 // Don't want any delay for form state sync changes. This will still post a
1034 // message so updates will get coalesced, but as soon as we spin the message
1035 // loop, it will generate an update.
1036 view_->set_send_content_state_immediately(true);
1037
1038 LoadHTML("<form method=\"POST\">"
1039 " <input type=\"text\" id=\"firstname\"/>"
1040 " <input type=\"text\" id=\"middlename\"/>"
1041 "</form>");
1042
1043 // Verify that "FormsSeen" sends the expected number of fields.
1044 ProcessPendingMessages();
1045 const IPC::Message* message = render_thread_.sink().GetUniqueMessageMatching(
1046 ViewHostMsg_FormsSeen::ID);
1047 ASSERT_NE(static_cast<IPC::Message*>(NULL), message);
1048 ViewHostMsg_FormsSeen::Param params;
1049 ViewHostMsg_FormsSeen::Read(message, &params);
1050 const std::vector<FormData>& forms = params.a;
1051 ASSERT_EQ(1UL, forms.size());
1052 ASSERT_EQ(2UL, forms[0].fields.size());
1053 EXPECT_TRUE(forms[0].fields[0].StrictlyEqualsHack(
1054 FormField(string16(),
1055 ASCIIToUTF16("firstname"),
1056 string16(),
1057 ASCIIToUTF16("text"),
1058 20))) << forms[0].fields[0];
1059 EXPECT_TRUE(forms[0].fields[1].StrictlyEqualsHack(
1060 FormField(string16(),
1061 ASCIIToUTF16("middlename"),
1062 string16(),
1063 ASCIIToUTF16("text"),
1064 20))) << forms[0].fields[1];
1065
1066 // Verify that |didAcceptAutoFillSuggestion()| sets the value of the expected
1067 // field.
1068 WebFrame* web_frame = GetMainFrame();
1069 WebDocument document = web_frame->document();
1070 WebInputElement firstname =
1071 document.getElementById("firstname").to<WebInputElement>();
1072 WebInputElement middlename =
1073 document.getElementById("middlename").to<WebInputElement>();
1074 middlename.setAutofilled(true);
1075
1076 // Accept a suggestion in a form that has been auto-filled. This triggers
1077 // the direct filling of the firstname element with value parameter.
1078 view_->didAcceptAutoFillSuggestion(firstname,
1079 WebKit::WebString::fromUTF8("David"),
1080 WebKit::WebString(),
1081 0,
1082 0);
1083
1084 ProcessPendingMessages();
1085 const IPC::Message* message2 = render_thread_.sink().GetUniqueMessageMatching(
1086 ViewHostMsg_FillAutoFillFormData::ID);
1087
1088 // No message should be sent in this case. |firstname| is filled directly.
1089 ASSERT_EQ(static_cast<IPC::Message*>(NULL), message2);
1090 EXPECT_EQ(firstname.value(), WebKit::WebString::fromUTF8("David"));
1091 }
OLDNEW
« no previous file with comments | « chrome/renderer/render_view_browsertest_mac.mm ('k') | chrome/renderer/render_view_unittest_mac.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698