a25b69c5c9f01b09f1089993f657809f283ea0fe
[platform/framework/web/crosswalk.git] / src / content / renderer / render_view_browsertest.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/basictypes.h"
6 #include "base/bind.h"
7 #include "base/callback.h"
8 #include "base/memory/shared_memory.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/win/windows_version.h"
12 #include "content/child/request_extra_data.h"
13 #include "content/child/service_worker/service_worker_network_provider.h"
14 #include "content/common/frame_messages.h"
15 #include "content/common/ssl_status_serialization.h"
16 #include "content/common/view_messages.h"
17 #include "content/public/browser/browser_context.h"
18 #include "content/public/browser/native_web_keyboard_event.h"
19 #include "content/public/browser/web_ui_controller_factory.h"
20 #include "content/public/common/bindings_policy.h"
21 #include "content/public/common/page_zoom.h"
22 #include "content/public/common/url_constants.h"
23 #include "content/public/common/url_utils.h"
24 #include "content/public/renderer/content_renderer_client.h"
25 #include "content/public/renderer/document_state.h"
26 #include "content/public/renderer/navigation_state.h"
27 #include "content/public/test/browser_test_utils.h"
28 #include "content/public/test/render_view_test.h"
29 #include "content/public/test/test_utils.h"
30 #include "content/renderer/accessibility/renderer_accessibility.h"
31 #include "content/renderer/accessibility/renderer_accessibility_complete.h"
32 #include "content/renderer/accessibility/renderer_accessibility_focus_only.h"
33 #include "content/renderer/history_controller.h"
34 #include "content/renderer/history_serialization.h"
35 #include "content/renderer/render_view_impl.h"
36 #include "content/shell/browser/shell.h"
37 #include "content/shell/browser/shell_browser_context.h"
38 #include "content/test/frame_load_waiter.h"
39 #include "content/test/mock_keyboard.h"
40 #include "net/base/net_errors.h"
41 #include "net/cert/cert_status_flags.h"
42 #include "testing/gtest/include/gtest/gtest.h"
43 #include "third_party/WebKit/public/platform/WebData.h"
44 #include "third_party/WebKit/public/platform/WebHTTPBody.h"
45 #include "third_party/WebKit/public/platform/WebString.h"
46 #include "third_party/WebKit/public/platform/WebURLResponse.h"
47 #include "third_party/WebKit/public/web/WebDataSource.h"
48 #include "third_party/WebKit/public/web/WebHistoryItem.h"
49 #include "third_party/WebKit/public/web/WebLocalFrame.h"
50 #include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
51 #include "third_party/WebKit/public/web/WebView.h"
52 #include "third_party/WebKit/public/web/WebWindowFeatures.h"
53 #include "ui/events/keycodes/keyboard_codes.h"
54 #include "ui/gfx/codec/jpeg_codec.h"
55 #include "ui/gfx/range/range.h"
56
57 #if defined(USE_AURA)
58 #include "ui/events/event.h"
59 #endif
60
61 #if defined(USE_AURA) && defined(USE_X11)
62 #include <X11/Xlib.h>
63 #include "ui/events/event_constants.h"
64 #include "ui/events/keycodes/keyboard_code_conversion.h"
65 #include "ui/events/test/events_test_utils_x11.h"
66 #endif
67
68 #if defined(USE_OZONE)
69 #include "ui/events/keycodes/keyboard_code_conversion.h"
70 #endif
71
72 using blink::WebFrame;
73 using blink::WebInputEvent;
74 using blink::WebLocalFrame;
75 using blink::WebMouseEvent;
76 using blink::WebRuntimeFeatures;
77 using blink::WebString;
78 using blink::WebTextDirection;
79 using blink::WebURLError;
80
81 namespace content {
82
83 namespace {
84
85 static const int kProxyRoutingId = 13;
86
87 #if (defined(USE_AURA) && defined(USE_X11)) || defined(USE_OZONE)
88 // Converts MockKeyboard::Modifiers to ui::EventFlags.
89 int ConvertMockKeyboardModifier(MockKeyboard::Modifiers modifiers) {
90   static struct ModifierMap {
91     MockKeyboard::Modifiers src;
92     int dst;
93   } kModifierMap[] = {
94     { MockKeyboard::LEFT_SHIFT, ui::EF_SHIFT_DOWN },
95     { MockKeyboard::RIGHT_SHIFT, ui::EF_SHIFT_DOWN },
96     { MockKeyboard::LEFT_CONTROL, ui::EF_CONTROL_DOWN },
97     { MockKeyboard::RIGHT_CONTROL, ui::EF_CONTROL_DOWN },
98     { MockKeyboard::LEFT_ALT,  ui::EF_ALT_DOWN },
99     { MockKeyboard::RIGHT_ALT, ui::EF_ALT_DOWN },
100   };
101   int flags = 0;
102   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kModifierMap); ++i) {
103     if (kModifierMap[i].src & modifiers) {
104       flags |= kModifierMap[i].dst;
105     }
106   }
107   return flags;
108 }
109 #endif
110
111 class WebUITestWebUIControllerFactory : public WebUIControllerFactory {
112  public:
113   virtual WebUIController* CreateWebUIControllerForURL(
114       WebUI* web_ui, const GURL& url) const OVERRIDE {
115     return NULL;
116   }
117   virtual WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
118                                      const GURL& url) const OVERRIDE {
119     return WebUI::kNoWebUI;
120   }
121   virtual bool UseWebUIForURL(BrowserContext* browser_context,
122                               const GURL& url) const OVERRIDE {
123     return HasWebUIScheme(url);
124   }
125   virtual bool UseWebUIBindingsForURL(BrowserContext* browser_context,
126                                       const GURL& url) const OVERRIDE {
127     return HasWebUIScheme(url);
128   }
129 };
130
131 class RenderViewImplTest : public RenderViewTest {
132  public:
133   RenderViewImplTest() {
134     // Attach a pseudo keyboard device to this object.
135     mock_keyboard_.reset(new MockKeyboard());
136   }
137
138   virtual ~RenderViewImplTest() {}
139
140   virtual void SetUp() OVERRIDE {
141     RenderViewTest::SetUp();
142     // Enable Blink's experimental and test only features so that test code
143     // does not have to bother enabling each feature.
144     WebRuntimeFeatures::enableExperimentalFeatures(true);
145     WebRuntimeFeatures::enableTestOnlyFeatures(true);
146   }
147
148   RenderViewImpl* view() {
149     return static_cast<RenderViewImpl*>(view_);
150   }
151
152   RenderFrameImpl* frame() {
153     return static_cast<RenderFrameImpl*>(view()->GetMainRenderFrame());
154   }
155
156   // Sends IPC messages that emulates a key-press event.
157   int SendKeyEvent(MockKeyboard::Layout layout,
158                    int key_code,
159                    MockKeyboard::Modifiers modifiers,
160                    base::string16* output) {
161 #if defined(OS_WIN)
162     // Retrieve the Unicode character for the given tuple (keyboard-layout,
163     // key-code, and modifiers).
164     // Exit when a keyboard-layout driver cannot assign a Unicode character to
165     // the tuple to prevent sending an invalid key code to the RenderView
166     // object.
167     CHECK(mock_keyboard_.get());
168     CHECK(output);
169     int length = mock_keyboard_->GetCharacters(layout, key_code, modifiers,
170                                                output);
171     if (length != 1)
172       return -1;
173
174     // Create IPC messages from Windows messages and send them to our
175     // back-end.
176     // A keyboard event of Windows consists of three Windows messages:
177     // WM_KEYDOWN, WM_CHAR, and WM_KEYUP.
178     // WM_KEYDOWN and WM_KEYUP sends virtual-key codes. On the other hand,
179     // WM_CHAR sends a composed Unicode character.
180     MSG msg1 = { NULL, WM_KEYDOWN, key_code, 0 };
181 #if defined(USE_AURA)
182     ui::KeyEvent evt1(msg1, false);
183     NativeWebKeyboardEvent keydown_event(&evt1);
184 #else
185     NativeWebKeyboardEvent keydown_event(msg1);
186 #endif
187     SendNativeKeyEvent(keydown_event);
188
189     MSG msg2 = { NULL, WM_CHAR, (*output)[0], 0 };
190 #if defined(USE_AURA)
191     ui::KeyEvent evt2(msg2, true);
192     NativeWebKeyboardEvent char_event(&evt2);
193 #else
194     NativeWebKeyboardEvent char_event(msg2);
195 #endif
196     SendNativeKeyEvent(char_event);
197
198     MSG msg3 = { NULL, WM_KEYUP, key_code, 0 };
199 #if defined(USE_AURA)
200     ui::KeyEvent evt3(msg3, false);
201     NativeWebKeyboardEvent keyup_event(&evt3);
202 #else
203     NativeWebKeyboardEvent keyup_event(msg3);
204 #endif
205     SendNativeKeyEvent(keyup_event);
206
207     return length;
208 #elif defined(USE_AURA) && defined(USE_X11)
209     // We ignore |layout|, which means we are only testing the layout of the
210     // current locale. TODO(mazda): fix this to respect |layout|.
211     CHECK(output);
212     const int flags = ConvertMockKeyboardModifier(modifiers);
213
214     ui::ScopedXI2Event xevent;
215     xevent.InitKeyEvent(ui::ET_KEY_PRESSED,
216                         static_cast<ui::KeyboardCode>(key_code),
217                         flags);
218     ui::KeyEvent event1(xevent, false);
219     NativeWebKeyboardEvent keydown_event(&event1);
220     SendNativeKeyEvent(keydown_event);
221
222     xevent.InitKeyEvent(ui::ET_KEY_PRESSED,
223                         static_cast<ui::KeyboardCode>(key_code),
224                         flags);
225     ui::KeyEvent event2(xevent, true);
226     NativeWebKeyboardEvent char_event(&event2);
227     SendNativeKeyEvent(char_event);
228
229     xevent.InitKeyEvent(ui::ET_KEY_RELEASED,
230                         static_cast<ui::KeyboardCode>(key_code),
231                         flags);
232     ui::KeyEvent event3(xevent, false);
233     NativeWebKeyboardEvent keyup_event(&event3);
234     SendNativeKeyEvent(keyup_event);
235
236     long c = GetCharacterFromKeyCode(static_cast<ui::KeyboardCode>(key_code),
237                                      flags);
238     output->assign(1, static_cast<base::char16>(c));
239     return 1;
240 #elif defined(USE_OZONE)
241     const int flags = ConvertMockKeyboardModifier(modifiers);
242
243     // Ozone's native events are ui::Events. So first create the "native" event,
244     // then create the actual ui::KeyEvent with the native event.
245     ui::KeyEvent keydown_native_event(ui::ET_KEY_PRESSED,
246                                    static_cast<ui::KeyboardCode>(key_code),
247                                    flags,
248                                    true);
249     ui::KeyEvent keydown_event(&keydown_native_event, false);
250     NativeWebKeyboardEvent keydown_web_event(&keydown_event);
251     SendNativeKeyEvent(keydown_web_event);
252
253     ui::KeyEvent char_native_event(ui::ET_KEY_PRESSED,
254                                    static_cast<ui::KeyboardCode>(key_code),
255                                    flags,
256                                    true);
257     ui::KeyEvent char_event(&char_native_event, true);
258     NativeWebKeyboardEvent char_web_event(&char_event);
259     SendNativeKeyEvent(char_web_event);
260
261     ui::KeyEvent keyup_native_event(ui::ET_KEY_RELEASED,
262                                     static_cast<ui::KeyboardCode>(key_code),
263                                     flags,
264                                     true);
265     ui::KeyEvent keyup_event(&keyup_native_event, false);
266     NativeWebKeyboardEvent keyup_web_event(&keyup_event);
267     SendNativeKeyEvent(keyup_web_event);
268
269     long c = GetCharacterFromKeyCode(static_cast<ui::KeyboardCode>(key_code),
270                                      flags);
271     output->assign(1, static_cast<base::char16>(c));
272     return 1;
273 #else
274     NOTIMPLEMENTED();
275     return L'\0';
276 #endif
277   }
278
279  private:
280   scoped_ptr<MockKeyboard> mock_keyboard_;
281 };
282
283 }  // namespace
284
285 // Test that we get form state change notifications when input fields change.
286 TEST_F(RenderViewImplTest, DISABLED_OnNavStateChanged) {
287   // Don't want any delay for form state sync changes. This will still post a
288   // message so updates will get coalesced, but as soon as we spin the message
289   // loop, it will generate an update.
290   view()->set_send_content_state_immediately(true);
291
292   LoadHTML("<input type=\"text\" id=\"elt_text\"></input>");
293
294   // We should NOT have gotten a form state change notification yet.
295   EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching(
296       ViewHostMsg_UpdateState::ID));
297   render_thread_->sink().ClearMessages();
298
299   // Change the value of the input. We should have gotten an update state
300   // notification. We need to spin the message loop to catch this update.
301   ExecuteJavaScript("document.getElementById('elt_text').value = 'foo';");
302   ProcessPendingMessages();
303   EXPECT_TRUE(render_thread_->sink().GetUniqueMessageMatching(
304       ViewHostMsg_UpdateState::ID));
305 }
306
307 TEST_F(RenderViewImplTest, OnNavigationHttpPost) {
308   FrameMsg_Navigate_Params nav_params;
309
310   // An http url will trigger a resource load so cannot be used here.
311   nav_params.url = GURL("data:text/html,<div>Page</div>");
312   nav_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
313   nav_params.transition = PAGE_TRANSITION_TYPED;
314   nav_params.page_id = -1;
315   nav_params.is_post = true;
316
317   // Set up post data.
318   const unsigned char* raw_data = reinterpret_cast<const unsigned char*>(
319       "post \0\ndata");
320   const unsigned int length = 11;
321   const std::vector<unsigned char> post_data(raw_data, raw_data + length);
322   nav_params.browser_initiated_post_data = post_data;
323
324   frame()->OnNavigate(nav_params);
325   ProcessPendingMessages();
326
327   const IPC::Message* frame_navigate_msg =
328       render_thread_->sink().GetUniqueMessageMatching(
329           FrameHostMsg_DidCommitProvisionalLoad::ID);
330   EXPECT_TRUE(frame_navigate_msg);
331
332   FrameHostMsg_DidCommitProvisionalLoad::Param host_nav_params;
333   FrameHostMsg_DidCommitProvisionalLoad::Read(frame_navigate_msg,
334                                               &host_nav_params);
335   EXPECT_TRUE(host_nav_params.a.is_post);
336
337   // Check post data sent to browser matches
338   EXPECT_TRUE(host_nav_params.a.page_state.IsValid());
339   scoped_ptr<HistoryEntry> entry =
340       PageStateToHistoryEntry(host_nav_params.a.page_state);
341   blink::WebHTTPBody body = entry->root().httpBody();
342   blink::WebHTTPBody::Element element;
343   bool successful = body.elementAt(0, element);
344   EXPECT_TRUE(successful);
345   EXPECT_EQ(blink::WebHTTPBody::Element::TypeData, element.type);
346   EXPECT_EQ(length, element.data.size());
347   EXPECT_EQ(0, memcmp(raw_data, element.data.data(), length));
348 }
349
350 TEST_F(RenderViewImplTest, DecideNavigationPolicy) {
351   WebUITestWebUIControllerFactory factory;
352   WebUIControllerFactory::RegisterFactory(&factory);
353
354   DocumentState state;
355   state.set_navigation_state(NavigationState::CreateContentInitiated());
356
357   // Navigations to normal HTTP URLs can be handled locally.
358   blink::WebURLRequest request(GURL("http://foo.com"));
359   blink::WebNavigationPolicy policy = frame()->decidePolicyForNavigation(
360           GetMainFrame(),
361           &state,
362           request,
363           blink::WebNavigationTypeLinkClicked,
364           blink::WebNavigationPolicyCurrentTab,
365           false);
366   EXPECT_EQ(blink::WebNavigationPolicyCurrentTab, policy);
367
368   // Verify that form posts to WebUI URLs will be sent to the browser process.
369   blink::WebURLRequest form_request(GURL("chrome://foo"));
370   form_request.setHTTPMethod("POST");
371   policy = frame()->decidePolicyForNavigation(
372       GetMainFrame(),
373       &state,
374       form_request,
375       blink::WebNavigationTypeFormSubmitted,
376       blink::WebNavigationPolicyCurrentTab,
377       false);
378   EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy);
379
380   // Verify that popup links to WebUI URLs also are sent to browser.
381   blink::WebURLRequest popup_request(GURL("chrome://foo"));
382   policy = frame()->decidePolicyForNavigation(
383       GetMainFrame(),
384       &state,
385       popup_request,
386       blink::WebNavigationTypeLinkClicked,
387       blink::WebNavigationPolicyNewForegroundTab,
388       false);
389   EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy);
390 }
391
392 TEST_F(RenderViewImplTest, DecideNavigationPolicyHandlesAllTopLevel) {
393   DocumentState state;
394   state.set_navigation_state(NavigationState::CreateContentInitiated());
395
396   RendererPreferences prefs = view()->renderer_preferences();
397   prefs.browser_handles_all_top_level_requests = true;
398   view()->OnSetRendererPrefs(prefs);
399
400   const blink::WebNavigationType kNavTypes[] = {
401     blink::WebNavigationTypeLinkClicked,
402     blink::WebNavigationTypeFormSubmitted,
403     blink::WebNavigationTypeBackForward,
404     blink::WebNavigationTypeReload,
405     blink::WebNavigationTypeFormResubmitted,
406     blink::WebNavigationTypeOther,
407   };
408
409   blink::WebURLRequest request(GURL("http://foo.com"));
410   for (size_t i = 0; i < arraysize(kNavTypes); ++i) {
411     blink::WebNavigationPolicy policy = frame()->decidePolicyForNavigation(
412         GetMainFrame(),
413         &state,
414         request,
415         kNavTypes[i],
416         blink::WebNavigationPolicyCurrentTab,
417         false);
418     EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy);
419   }
420 }
421
422 TEST_F(RenderViewImplTest, DecideNavigationPolicyForWebUI) {
423   // Enable bindings to simulate a WebUI view.
424   view()->OnAllowBindings(BINDINGS_POLICY_WEB_UI);
425
426   DocumentState state;
427   state.set_navigation_state(NavigationState::CreateContentInitiated());
428
429   // Navigations to normal HTTP URLs will be sent to browser process.
430   blink::WebURLRequest request(GURL("http://foo.com"));
431   blink::WebNavigationPolicy policy = frame()->decidePolicyForNavigation(
432       GetMainFrame(),
433       &state,
434       request,
435       blink::WebNavigationTypeLinkClicked,
436       blink::WebNavigationPolicyCurrentTab,
437       false);
438   EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy);
439
440   // Navigations to WebUI URLs will also be sent to browser process.
441   blink::WebURLRequest webui_request(GURL("chrome://foo"));
442   policy = frame()->decidePolicyForNavigation(
443       GetMainFrame(),
444       &state,
445       webui_request,
446       blink::WebNavigationTypeLinkClicked,
447       blink::WebNavigationPolicyCurrentTab,
448       false);
449   EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy);
450
451   // Verify that form posts to data URLs will be sent to the browser process.
452   blink::WebURLRequest data_request(GURL("data:text/html,foo"));
453   data_request.setHTTPMethod("POST");
454   policy = frame()->decidePolicyForNavigation(
455       GetMainFrame(),
456       &state,
457       data_request,
458       blink::WebNavigationTypeFormSubmitted,
459       blink::WebNavigationPolicyCurrentTab,
460       false);
461   EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy);
462
463   // Verify that a popup that creates a view first and then navigates to a
464   // normal HTTP URL will be sent to the browser process, even though the
465   // new view does not have any enabled_bindings_.
466   blink::WebURLRequest popup_request(GURL("http://foo.com"));
467   blink::WebView* new_web_view = view()->createView(
468       GetMainFrame(), popup_request, blink::WebWindowFeatures(), "foo",
469       blink::WebNavigationPolicyNewForegroundTab, false);
470   RenderViewImpl* new_view = RenderViewImpl::FromWebView(new_web_view);
471   policy = static_cast<RenderFrameImpl*>(new_view->GetMainRenderFrame())->
472       decidePolicyForNavigation(
473           new_web_view->mainFrame()->toWebLocalFrame(),
474           &state,
475           popup_request,
476           blink::WebNavigationTypeLinkClicked,
477           blink::WebNavigationPolicyNewForegroundTab,
478           false);
479   EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy);
480
481   // Clean up after the new view so we don't leak it.
482   new_view->Close();
483   new_view->Release();
484 }
485
486 // Ensure the RenderViewImpl sends an ACK to a SwapOut request, even if it is
487 // already swapped out.  http://crbug.com/93427.
488 TEST_F(RenderViewImplTest, SendSwapOutACK) {
489   LoadHTML("<div>Page A</div>");
490   int initial_page_id = view()->GetPageId();
491
492   // Respond to a swap out request.
493   view()->main_render_frame()->OnSwapOut(kProxyRoutingId);
494
495   // Ensure the swap out commits synchronously.
496   EXPECT_NE(initial_page_id, view()->GetPageId());
497
498   // Check for a valid OnSwapOutACK.
499   const IPC::Message* msg = render_thread_->sink().GetUniqueMessageMatching(
500       FrameHostMsg_SwapOut_ACK::ID);
501   ASSERT_TRUE(msg);
502
503   // It is possible to get another swap out request.  Ensure that we send
504   // an ACK, even if we don't have to do anything else.
505   render_thread_->sink().ClearMessages();
506   view()->main_render_frame()->OnSwapOut(kProxyRoutingId);
507   const IPC::Message* msg2 = render_thread_->sink().GetUniqueMessageMatching(
508       FrameHostMsg_SwapOut_ACK::ID);
509   ASSERT_TRUE(msg2);
510
511   // If we navigate back to this RenderView, ensure we don't send a state
512   // update for the swapped out URL.  (http://crbug.com/72235)
513   FrameMsg_Navigate_Params nav_params;
514   nav_params.url = GURL("data:text/html,<div>Page B</div>");
515   nav_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
516   nav_params.transition = PAGE_TRANSITION_TYPED;
517   nav_params.current_history_list_length = 1;
518   nav_params.current_history_list_offset = 0;
519   nav_params.pending_history_list_offset = 1;
520   nav_params.page_id = -1;
521   frame()->OnNavigate(nav_params);
522   ProcessPendingMessages();
523   const IPC::Message* msg3 = render_thread_->sink().GetUniqueMessageMatching(
524       ViewHostMsg_UpdateState::ID);
525   EXPECT_FALSE(msg3);
526 }
527
528 // Ensure the RenderViewImpl reloads the previous page if a reload request
529 // arrives while it is showing swappedout://.  http://crbug.com/143155.
530 TEST_F(RenderViewImplTest, ReloadWhileSwappedOut) {
531   // Load page A.
532   LoadHTML("<div>Page A</div>");
533
534   // Load page B, which will trigger an UpdateState message for page A.
535   LoadHTML("<div>Page B</div>");
536
537   // Check for a valid UpdateState message for page A.
538   ProcessPendingMessages();
539   const IPC::Message* msg_A = render_thread_->sink().GetUniqueMessageMatching(
540       ViewHostMsg_UpdateState::ID);
541   ASSERT_TRUE(msg_A);
542   ViewHostMsg_UpdateState::Param params;
543   ViewHostMsg_UpdateState::Read(msg_A, &params);
544   int page_id_A = params.a;
545   PageState state_A = params.b;
546   EXPECT_EQ(1, page_id_A);
547   render_thread_->sink().ClearMessages();
548
549   // Back to page A (page_id 1) and commit.
550   FrameMsg_Navigate_Params params_A;
551   params_A.navigation_type = FrameMsg_Navigate_Type::NORMAL;
552   params_A.transition = PAGE_TRANSITION_FORWARD_BACK;
553   params_A.current_history_list_length = 2;
554   params_A.current_history_list_offset = 1;
555   params_A.pending_history_list_offset = 0;
556   params_A.page_id = 1;
557   params_A.page_state = state_A;
558   frame()->OnNavigate(params_A);
559   ProcessPendingMessages();
560
561   // Respond to a swap out request.
562   view()->main_render_frame()->OnSwapOut(kProxyRoutingId);
563
564   // Check for a OnSwapOutACK.
565   const IPC::Message* msg = render_thread_->sink().GetUniqueMessageMatching(
566       FrameHostMsg_SwapOut_ACK::ID);
567   ASSERT_TRUE(msg);
568   render_thread_->sink().ClearMessages();
569
570   // It is possible to get a reload request at this point, containing the
571   // params.page_state of the initial page (e.g., if the new page fails the
572   // provisional load in the renderer process, after we unload the old page).
573   // Ensure the old page gets reloaded, not swappedout://.
574   FrameMsg_Navigate_Params nav_params;
575   nav_params.url = GURL("data:text/html,<div>Page A</div>");
576   nav_params.navigation_type = FrameMsg_Navigate_Type::RELOAD;
577   nav_params.transition = PAGE_TRANSITION_RELOAD;
578   nav_params.current_history_list_length = 2;
579   nav_params.current_history_list_offset = 0;
580   nav_params.pending_history_list_offset = 0;
581   nav_params.page_id = 1;
582   nav_params.page_state = state_A;
583   frame()->OnNavigate(nav_params);
584   ProcessPendingMessages();
585
586   // Verify page A committed, not swappedout://.
587   const IPC::Message* frame_navigate_msg =
588       render_thread_->sink().GetUniqueMessageMatching(
589           FrameHostMsg_DidCommitProvisionalLoad::ID);
590   EXPECT_TRUE(frame_navigate_msg);
591
592   // Read URL out of the parent trait of the params object.
593   FrameHostMsg_DidCommitProvisionalLoad::Param commit_params;
594   FrameHostMsg_DidCommitProvisionalLoad::Read(frame_navigate_msg,
595                                               &commit_params);
596   EXPECT_NE(GURL("swappedout://"), commit_params.a.url);
597 }
598
599
600 // Test that we get the correct UpdateState message when we go back twice
601 // quickly without committing.  Regression test for http://crbug.com/58082.
602 // Disabled: http://crbug.com/157357 .
603 TEST_F(RenderViewImplTest,  DISABLED_LastCommittedUpdateState) {
604   // Load page A.
605   LoadHTML("<div>Page A</div>");
606
607   // Load page B, which will trigger an UpdateState message for page A.
608   LoadHTML("<div>Page B</div>");
609
610   // Check for a valid UpdateState message for page A.
611   ProcessPendingMessages();
612   const IPC::Message* msg_A = render_thread_->sink().GetUniqueMessageMatching(
613       ViewHostMsg_UpdateState::ID);
614   ASSERT_TRUE(msg_A);
615   ViewHostMsg_UpdateState::Param param;
616   ViewHostMsg_UpdateState::Read(msg_A, &param);
617   int page_id_A = param.a;
618   PageState state_A = param.b;
619   EXPECT_EQ(1, page_id_A);
620   render_thread_->sink().ClearMessages();
621
622   // Load page C, which will trigger an UpdateState message for page B.
623   LoadHTML("<div>Page C</div>");
624
625   // Check for a valid UpdateState for page B.
626   ProcessPendingMessages();
627   const IPC::Message* msg_B = render_thread_->sink().GetUniqueMessageMatching(
628       ViewHostMsg_UpdateState::ID);
629   ASSERT_TRUE(msg_B);
630   ViewHostMsg_UpdateState::Read(msg_B, &param);
631   int page_id_B = param.a;
632   PageState state_B = param.b;
633   EXPECT_EQ(2, page_id_B);
634   EXPECT_NE(state_A, state_B);
635   render_thread_->sink().ClearMessages();
636
637   // Load page D, which will trigger an UpdateState message for page C.
638   LoadHTML("<div>Page D</div>");
639
640   // Check for a valid UpdateState for page C.
641   ProcessPendingMessages();
642   const IPC::Message* msg_C = render_thread_->sink().GetUniqueMessageMatching(
643       ViewHostMsg_UpdateState::ID);
644   ASSERT_TRUE(msg_C);
645   ViewHostMsg_UpdateState::Read(msg_C, &param);
646   int page_id_C = param.a;
647   PageState state_C = param.b;
648   EXPECT_EQ(3, page_id_C);
649   EXPECT_NE(state_B, state_C);
650   render_thread_->sink().ClearMessages();
651
652   // Go back to C and commit, preparing for our real test.
653   FrameMsg_Navigate_Params params_C;
654   params_C.navigation_type = FrameMsg_Navigate_Type::NORMAL;
655   params_C.transition = PAGE_TRANSITION_FORWARD_BACK;
656   params_C.current_history_list_length = 4;
657   params_C.current_history_list_offset = 3;
658   params_C.pending_history_list_offset = 2;
659   params_C.page_id = 3;
660   params_C.page_state = state_C;
661   frame()->OnNavigate(params_C);
662   ProcessPendingMessages();
663   render_thread_->sink().ClearMessages();
664
665   // Go back twice quickly, such that page B does not have a chance to commit.
666   // This leads to two changes to the back/forward list but only one change to
667   // the RenderView's page ID.
668
669   // Back to page B (page_id 2), without committing.
670   FrameMsg_Navigate_Params params_B;
671   params_B.navigation_type = FrameMsg_Navigate_Type::NORMAL;
672   params_B.transition = PAGE_TRANSITION_FORWARD_BACK;
673   params_B.current_history_list_length = 4;
674   params_B.current_history_list_offset = 2;
675   params_B.pending_history_list_offset = 1;
676   params_B.page_id = 2;
677   params_B.page_state = state_B;
678   frame()->OnNavigate(params_B);
679
680   // Back to page A (page_id 1) and commit.
681   FrameMsg_Navigate_Params params;
682   params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
683   params.transition = PAGE_TRANSITION_FORWARD_BACK;
684   params_B.current_history_list_length = 4;
685   params_B.current_history_list_offset = 2;
686   params_B.pending_history_list_offset = 0;
687   params.page_id = 1;
688   params.page_state = state_A;
689   frame()->OnNavigate(params);
690   ProcessPendingMessages();
691
692   // Now ensure that the UpdateState message we receive is consistent
693   // and represents page C in both page_id and state.
694   const IPC::Message* msg = render_thread_->sink().GetUniqueMessageMatching(
695       ViewHostMsg_UpdateState::ID);
696   ASSERT_TRUE(msg);
697   ViewHostMsg_UpdateState::Read(msg, &param);
698   int page_id = param.a;
699   PageState state = param.b;
700   EXPECT_EQ(page_id_C, page_id);
701   EXPECT_NE(state_A, state);
702   EXPECT_NE(state_B, state);
703   EXPECT_EQ(state_C, state);
704 }
705
706 // Test that the history_page_ids_ list can reveal when a stale back/forward
707 // navigation arrives from the browser and can be ignored.  See
708 // http://crbug.com/86758.
709 TEST_F(RenderViewImplTest, StaleNavigationsIgnored) {
710   // Load page A.
711   LoadHTML("<div>Page A</div>");
712   EXPECT_EQ(1, view()->history_list_length_);
713   EXPECT_EQ(0, view()->history_list_offset_);
714   EXPECT_EQ(1, view()->history_page_ids_[0]);
715
716   // Load page B, which will trigger an UpdateState message for page A.
717   LoadHTML("<div>Page B</div>");
718   EXPECT_EQ(2, view()->history_list_length_);
719   EXPECT_EQ(1, view()->history_list_offset_);
720   EXPECT_EQ(2, view()->history_page_ids_[1]);
721
722   // Check for a valid UpdateState message for page A.
723   ProcessPendingMessages();
724   const IPC::Message* msg_A = render_thread_->sink().GetUniqueMessageMatching(
725       ViewHostMsg_UpdateState::ID);
726   ASSERT_TRUE(msg_A);
727   ViewHostMsg_UpdateState::Param param;
728   ViewHostMsg_UpdateState::Read(msg_A, &param);
729   int page_id_A = param.a;
730   PageState state_A = param.b;
731   EXPECT_EQ(1, page_id_A);
732   render_thread_->sink().ClearMessages();
733
734   // Back to page A (page_id 1) and commit.
735   FrameMsg_Navigate_Params params_A;
736   params_A.navigation_type = FrameMsg_Navigate_Type::NORMAL;
737   params_A.transition = PAGE_TRANSITION_FORWARD_BACK;
738   params_A.current_history_list_length = 2;
739   params_A.current_history_list_offset = 1;
740   params_A.pending_history_list_offset = 0;
741   params_A.page_id = 1;
742   params_A.page_state = state_A;
743   frame()->OnNavigate(params_A);
744   ProcessPendingMessages();
745
746   // A new navigation commits, clearing the forward history.
747   LoadHTML("<div>Page C</div>");
748   EXPECT_EQ(2, view()->history_list_length_);
749   EXPECT_EQ(1, view()->history_list_offset_);
750   EXPECT_EQ(3, view()->history_page_ids_[1]);
751
752   // The browser then sends a stale navigation to B, which should be ignored.
753   FrameMsg_Navigate_Params params_B;
754   params_B.navigation_type = FrameMsg_Navigate_Type::NORMAL;
755   params_B.transition = PAGE_TRANSITION_FORWARD_BACK;
756   params_B.current_history_list_length = 2;
757   params_B.current_history_list_offset = 0;
758   params_B.pending_history_list_offset = 1;
759   params_B.page_id = 2;
760   params_B.page_state = state_A;  // Doesn't matter, just has to be present.
761   frame()->OnNavigate(params_B);
762
763   // State should be unchanged.
764   EXPECT_EQ(2, view()->history_list_length_);
765   EXPECT_EQ(1, view()->history_list_offset_);
766   EXPECT_EQ(3, view()->history_page_ids_[1]);
767 }
768
769 // Test that we do not ignore navigations after the entry limit is reached,
770 // in which case the browser starts dropping entries from the front.  In this
771 // case, we'll see a page_id mismatch but the RenderView's id will be older,
772 // not newer, than params.page_id.  Use this as a cue that we should update the
773 // state and not treat it like a navigation to a cropped forward history item.
774 // See http://crbug.com/89798.
775 TEST_F(RenderViewImplTest, DontIgnoreBackAfterNavEntryLimit) {
776   // Load page A.
777   LoadHTML("<div>Page A</div>");
778   EXPECT_EQ(1, view()->history_list_length_);
779   EXPECT_EQ(0, view()->history_list_offset_);
780   EXPECT_EQ(1, view()->history_page_ids_[0]);
781
782   // Load page B, which will trigger an UpdateState message for page A.
783   LoadHTML("<div>Page B</div>");
784   EXPECT_EQ(2, view()->history_list_length_);
785   EXPECT_EQ(1, view()->history_list_offset_);
786   EXPECT_EQ(2, view()->history_page_ids_[1]);
787
788   // Check for a valid UpdateState message for page A.
789   ProcessPendingMessages();
790   const IPC::Message* msg_A = render_thread_->sink().GetUniqueMessageMatching(
791       ViewHostMsg_UpdateState::ID);
792   ASSERT_TRUE(msg_A);
793   ViewHostMsg_UpdateState::Param param;
794   ViewHostMsg_UpdateState::Read(msg_A, &param);
795   int page_id_A = param.a;
796   PageState state_A = param.b;
797   EXPECT_EQ(1, page_id_A);
798   render_thread_->sink().ClearMessages();
799
800   // Load page C, which will trigger an UpdateState message for page B.
801   LoadHTML("<div>Page C</div>");
802   EXPECT_EQ(3, view()->history_list_length_);
803   EXPECT_EQ(2, view()->history_list_offset_);
804   EXPECT_EQ(3, view()->history_page_ids_[2]);
805
806   // Check for a valid UpdateState message for page B.
807   ProcessPendingMessages();
808   const IPC::Message* msg_B = render_thread_->sink().GetUniqueMessageMatching(
809       ViewHostMsg_UpdateState::ID);
810   ASSERT_TRUE(msg_B);
811   ViewHostMsg_UpdateState::Read(msg_B, &param);
812   int page_id_B = param.a;
813   PageState state_B = param.b;
814   EXPECT_EQ(2, page_id_B);
815   render_thread_->sink().ClearMessages();
816
817   // Suppose the browser has limited the number of NavigationEntries to 2.
818   // It has now dropped the first entry, but the renderer isn't notified.
819   // Ensure that going back to page B (page_id 2) at offset 0 is successful.
820   FrameMsg_Navigate_Params params_B;
821   params_B.navigation_type = FrameMsg_Navigate_Type::NORMAL;
822   params_B.transition = PAGE_TRANSITION_FORWARD_BACK;
823   params_B.current_history_list_length = 2;
824   params_B.current_history_list_offset = 1;
825   params_B.pending_history_list_offset = 0;
826   params_B.page_id = 2;
827   params_B.page_state = state_B;
828   frame()->OnNavigate(params_B);
829   ProcessPendingMessages();
830
831   EXPECT_EQ(2, view()->history_list_length_);
832   EXPECT_EQ(0, view()->history_list_offset_);
833   EXPECT_EQ(2, view()->history_page_ids_[0]);
834 }
835
836 // Test that our IME backend sends a notification message when the input focus
837 // changes.
838 TEST_F(RenderViewImplTest, OnImeTypeChanged) {
839   // Enable our IME backend code.
840   view()->OnSetInputMethodActive(true);
841
842   // Load an HTML page consisting of two input fields.
843   view()->set_send_content_state_immediately(true);
844   LoadHTML("<html>"
845            "<head>"
846            "</head>"
847            "<body>"
848            "<input id=\"test1\" type=\"text\" value=\"some text\"></input>"
849            "<input id=\"test2\" type=\"password\"></input>"
850            "<input id=\"test3\" type=\"text\" inputmode=\"verbatim\"></input>"
851            "<input id=\"test4\" type=\"text\" inputmode=\"latin\"></input>"
852            "<input id=\"test5\" type=\"text\" inputmode=\"latin-name\"></input>"
853            "<input id=\"test6\" type=\"text\" inputmode=\"latin-prose\">"
854                "</input>"
855            "<input id=\"test7\" type=\"text\" inputmode=\"full-width-latin\">"
856                "</input>"
857            "<input id=\"test8\" type=\"text\" inputmode=\"kana\"></input>"
858            "<input id=\"test9\" type=\"text\" inputmode=\"katakana\"></input>"
859            "<input id=\"test10\" type=\"text\" inputmode=\"numeric\"></input>"
860            "<input id=\"test11\" type=\"text\" inputmode=\"tel\"></input>"
861            "<input id=\"test12\" type=\"text\" inputmode=\"email\"></input>"
862            "<input id=\"test13\" type=\"text\" inputmode=\"url\"></input>"
863            "<input id=\"test14\" type=\"text\" inputmode=\"unknown\"></input>"
864            "<input id=\"test15\" type=\"text\" inputmode=\"verbatim\"></input>"
865            "</body>"
866            "</html>");
867   render_thread_->sink().ClearMessages();
868
869   struct InputModeTestCase {
870     const char* input_id;
871     ui::TextInputMode expected_mode;
872   };
873   static const InputModeTestCase kInputModeTestCases[] = {
874      {"test1", ui::TEXT_INPUT_MODE_DEFAULT},
875      {"test3", ui::TEXT_INPUT_MODE_VERBATIM},
876      {"test4", ui::TEXT_INPUT_MODE_LATIN},
877      {"test5", ui::TEXT_INPUT_MODE_LATIN_NAME},
878      {"test6", ui::TEXT_INPUT_MODE_LATIN_PROSE},
879      {"test7", ui::TEXT_INPUT_MODE_FULL_WIDTH_LATIN},
880      {"test8", ui::TEXT_INPUT_MODE_KANA},
881      {"test9", ui::TEXT_INPUT_MODE_KATAKANA},
882      {"test10", ui::TEXT_INPUT_MODE_NUMERIC},
883      {"test11", ui::TEXT_INPUT_MODE_TEL},
884      {"test12", ui::TEXT_INPUT_MODE_EMAIL},
885      {"test13", ui::TEXT_INPUT_MODE_URL},
886      {"test14", ui::TEXT_INPUT_MODE_DEFAULT},
887      {"test15", ui::TEXT_INPUT_MODE_VERBATIM},
888   };
889
890   const int kRepeatCount = 10;
891   for (int i = 0; i < kRepeatCount; i++) {
892     // Move the input focus to the first <input> element, where we should
893     // activate IMEs.
894     ExecuteJavaScript("document.getElementById('test1').focus();");
895     ProcessPendingMessages();
896     render_thread_->sink().ClearMessages();
897
898     // Update the IME status and verify if our IME backend sends an IPC message
899     // to activate IMEs.
900     view()->UpdateTextInputState(
901         RenderWidget::NO_SHOW_IME, RenderWidget::FROM_NON_IME);
902     const IPC::Message* msg = render_thread_->sink().GetMessageAt(0);
903     EXPECT_TRUE(msg != NULL);
904     EXPECT_EQ(ViewHostMsg_TextInputStateChanged::ID, msg->type());
905     ViewHostMsg_TextInputStateChanged::Param params;
906     ViewHostMsg_TextInputStateChanged::Read(msg, &params);
907     ViewHostMsg_TextInputState_Params p = params.a;
908     EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, p.type);
909     EXPECT_EQ(true, p.can_compose_inline);
910
911     // Move the input focus to the second <input> element, where we should
912     // de-activate IMEs.
913     ExecuteJavaScript("document.getElementById('test2').focus();");
914     ProcessPendingMessages();
915     render_thread_->sink().ClearMessages();
916
917     // Update the IME status and verify if our IME backend sends an IPC message
918     // to de-activate IMEs.
919     view()->UpdateTextInputState(
920         RenderWidget::NO_SHOW_IME, RenderWidget::FROM_NON_IME);
921     msg = render_thread_->sink().GetMessageAt(0);
922     EXPECT_TRUE(msg != NULL);
923     EXPECT_EQ(ViewHostMsg_TextInputStateChanged::ID, msg->type());
924     ViewHostMsg_TextInputStateChanged::Read(msg, &params);
925     EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, params.a.type);
926
927     for (size_t j = 0; j < ARRAYSIZE_UNSAFE(kInputModeTestCases); j++) {
928       const InputModeTestCase* test_case = &kInputModeTestCases[j];
929       std::string javascript =
930           base::StringPrintf("document.getElementById('%s').focus();",
931                              test_case->input_id);
932       // Move the input focus to the target <input> element, where we should
933       // activate IMEs.
934       ExecuteJavaScript(javascript.c_str());
935       ProcessPendingMessages();
936       render_thread_->sink().ClearMessages();
937
938       // Update the IME status and verify if our IME backend sends an IPC
939       // message to activate IMEs.
940       view()->UpdateTextInputState(
941         RenderWidget::NO_SHOW_IME, RenderWidget::FROM_NON_IME);
942       msg = render_thread_->sink().GetMessageAt(0);
943       EXPECT_TRUE(msg != NULL);
944       EXPECT_EQ(ViewHostMsg_TextInputStateChanged::ID, msg->type());
945       ViewHostMsg_TextInputStateChanged::Read(msg, &params);
946       EXPECT_EQ(test_case->expected_mode, params.a.mode);
947     }
948   }
949 }
950
951 // Test that our IME backend can compose CJK words.
952 // Our IME front-end sends many platform-independent messages to the IME backend
953 // while it composes CJK words. This test sends the minimal messages captured
954 // on my local environment directly to the IME backend to verify if the backend
955 // can compose CJK words without any problems.
956 // This test uses an array of command sets because an IME composotion does not
957 // only depends on IME events, but also depends on window events, e.g. moving
958 // the window focus while composing a CJK text. To handle such complicated
959 // cases, this test should not only call IME-related functions in the
960 // RenderWidget class, but also call some RenderWidget members, e.g.
961 // ExecuteJavaScript(), RenderWidget::OnSetFocus(), etc.
962 TEST_F(RenderViewImplTest, ImeComposition) {
963   enum ImeCommand {
964     IME_INITIALIZE,
965     IME_SETINPUTMODE,
966     IME_SETFOCUS,
967     IME_SETCOMPOSITION,
968     IME_CONFIRMCOMPOSITION,
969     IME_CANCELCOMPOSITION
970   };
971   struct ImeMessage {
972     ImeCommand command;
973     bool enable;
974     int selection_start;
975     int selection_end;
976     const wchar_t* ime_string;
977     const wchar_t* result;
978   };
979   static const ImeMessage kImeMessages[] = {
980     // Scenario 1: input a Chinese word with Microsoft IME (on Vista).
981     {IME_INITIALIZE, true, 0, 0, NULL, NULL},
982     {IME_SETINPUTMODE, true, 0, 0, NULL, NULL},
983     {IME_SETFOCUS, true, 0, 0, NULL, NULL},
984     {IME_SETCOMPOSITION, false, 1, 1, L"n", L"n"},
985     {IME_SETCOMPOSITION, false, 2, 2, L"ni", L"ni"},
986     {IME_SETCOMPOSITION, false, 3, 3, L"nih", L"nih"},
987     {IME_SETCOMPOSITION, false, 4, 4, L"niha", L"niha"},
988     {IME_SETCOMPOSITION, false, 5, 5, L"nihao", L"nihao"},
989     {IME_CONFIRMCOMPOSITION, false, -1, -1, L"\x4F60\x597D", L"\x4F60\x597D"},
990     // Scenario 2: input a Japanese word with Microsoft IME (on Vista).
991     {IME_INITIALIZE, true, 0, 0, NULL, NULL},
992     {IME_SETINPUTMODE, true, 0, 0, NULL, NULL},
993     {IME_SETFOCUS, true, 0, 0, NULL, NULL},
994     {IME_SETCOMPOSITION, false, 0, 1, L"\xFF4B", L"\xFF4B"},
995     {IME_SETCOMPOSITION, false, 0, 1, L"\x304B", L"\x304B"},
996     {IME_SETCOMPOSITION, false, 0, 2, L"\x304B\xFF4E", L"\x304B\xFF4E"},
997     {IME_SETCOMPOSITION, false, 0, 3, L"\x304B\x3093\xFF4A",
998      L"\x304B\x3093\xFF4A"},
999     {IME_SETCOMPOSITION, false, 0, 3, L"\x304B\x3093\x3058",
1000      L"\x304B\x3093\x3058"},
1001     {IME_SETCOMPOSITION, false, 0, 2, L"\x611F\x3058", L"\x611F\x3058"},
1002     {IME_SETCOMPOSITION, false, 0, 2, L"\x6F22\x5B57", L"\x6F22\x5B57"},
1003     {IME_CONFIRMCOMPOSITION, false, -1, -1, L"", L"\x6F22\x5B57"},
1004     {IME_CANCELCOMPOSITION, false, -1, -1, L"", L"\x6F22\x5B57"},
1005     // Scenario 3: input a Korean word with Microsot IME (on Vista).
1006     {IME_INITIALIZE, true, 0, 0, NULL, NULL},
1007     {IME_SETINPUTMODE, true, 0, 0, NULL, NULL},
1008     {IME_SETFOCUS, true, 0, 0, NULL, NULL},
1009     {IME_SETCOMPOSITION, false, 0, 1, L"\x3147", L"\x3147"},
1010     {IME_SETCOMPOSITION, false, 0, 1, L"\xC544", L"\xC544"},
1011     {IME_SETCOMPOSITION, false, 0, 1, L"\xC548", L"\xC548"},
1012     {IME_CONFIRMCOMPOSITION, false, -1, -1, L"", L"\xC548"},
1013     {IME_SETCOMPOSITION, false, 0, 1, L"\x3134", L"\xC548\x3134"},
1014     {IME_SETCOMPOSITION, false, 0, 1, L"\xB140", L"\xC548\xB140"},
1015     {IME_SETCOMPOSITION, false, 0, 1, L"\xB155", L"\xC548\xB155"},
1016     {IME_CANCELCOMPOSITION, false, -1, -1, L"", L"\xC548"},
1017     {IME_SETCOMPOSITION, false, 0, 1, L"\xB155", L"\xC548\xB155"},
1018     {IME_CONFIRMCOMPOSITION, false, -1, -1, L"", L"\xC548\xB155"},
1019   };
1020
1021   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kImeMessages); i++) {
1022     const ImeMessage* ime_message = &kImeMessages[i];
1023     switch (ime_message->command) {
1024       case IME_INITIALIZE:
1025         // Load an HTML page consisting of a content-editable <div> element,
1026         // and move the input focus to the <div> element, where we can use
1027         // IMEs.
1028         view()->OnSetInputMethodActive(ime_message->enable);
1029         view()->set_send_content_state_immediately(true);
1030         LoadHTML("<html>"
1031                 "<head>"
1032                 "</head>"
1033                 "<body>"
1034                 "<div id=\"test1\" contenteditable=\"true\"></div>"
1035                 "</body>"
1036                 "</html>");
1037         ExecuteJavaScript("document.getElementById('test1').focus();");
1038         break;
1039
1040       case IME_SETINPUTMODE:
1041         // Activate (or deactivate) our IME back-end.
1042         view()->OnSetInputMethodActive(ime_message->enable);
1043         break;
1044
1045       case IME_SETFOCUS:
1046         // Update the window focus.
1047         view()->OnSetFocus(ime_message->enable);
1048         break;
1049
1050       case IME_SETCOMPOSITION:
1051         view()->OnImeSetComposition(
1052             base::WideToUTF16(ime_message->ime_string),
1053             std::vector<blink::WebCompositionUnderline>(),
1054             ime_message->selection_start,
1055             ime_message->selection_end);
1056         break;
1057
1058       case IME_CONFIRMCOMPOSITION:
1059         view()->OnImeConfirmComposition(
1060             base::WideToUTF16(ime_message->ime_string),
1061             gfx::Range::InvalidRange(),
1062             false);
1063         break;
1064
1065       case IME_CANCELCOMPOSITION:
1066         view()->OnImeSetComposition(
1067             base::string16(),
1068             std::vector<blink::WebCompositionUnderline>(),
1069             0, 0);
1070         break;
1071     }
1072
1073     // Update the status of our IME back-end.
1074     // TODO(hbono): we should verify messages to be sent from the back-end.
1075     view()->UpdateTextInputState(
1076         RenderWidget::NO_SHOW_IME, RenderWidget::FROM_NON_IME);
1077     ProcessPendingMessages();
1078     render_thread_->sink().ClearMessages();
1079
1080     if (ime_message->result) {
1081       // Retrieve the content of this page and compare it with the expected
1082       // result.
1083       const int kMaxOutputCharacters = 128;
1084       base::string16 output =
1085           GetMainFrame()->contentAsText(kMaxOutputCharacters);
1086       EXPECT_EQ(base::WideToUTF16(ime_message->result), output);
1087     }
1088   }
1089 }
1090
1091 // Test that the RenderView::OnSetTextDirection() function can change the text
1092 // direction of the selected input element.
1093 TEST_F(RenderViewImplTest, OnSetTextDirection) {
1094   // Load an HTML page consisting of a <textarea> element and a <div> element.
1095   // This test changes the text direction of the <textarea> element, and
1096   // writes the values of its 'dir' attribute and its 'direction' property to
1097   // verify that the text direction is changed.
1098   view()->set_send_content_state_immediately(true);
1099   LoadHTML("<html>"
1100            "<head>"
1101            "</head>"
1102            "<body>"
1103            "<textarea id=\"test\"></textarea>"
1104            "<div id=\"result\" contenteditable=\"true\"></div>"
1105            "</body>"
1106            "</html>");
1107   render_thread_->sink().ClearMessages();
1108
1109   static const struct {
1110     WebTextDirection direction;
1111     const wchar_t* expected_result;
1112   } kTextDirection[] = {
1113     { blink::WebTextDirectionRightToLeft, L"\x000A" L"rtl,rtl" },
1114     { blink::WebTextDirectionLeftToRight, L"\x000A" L"ltr,ltr" },
1115   };
1116   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTextDirection); ++i) {
1117     // Set the text direction of the <textarea> element.
1118     ExecuteJavaScript("document.getElementById('test').focus();");
1119     view()->OnSetTextDirection(kTextDirection[i].direction);
1120
1121     // Write the values of its DOM 'dir' attribute and its CSS 'direction'
1122     // property to the <div> element.
1123     ExecuteJavaScript("var result = document.getElementById('result');"
1124                       "var node = document.getElementById('test');"
1125                       "var style = getComputedStyle(node, null);"
1126                       "result.innerText ="
1127                       "    node.getAttribute('dir') + ',' +"
1128                       "    style.getPropertyValue('direction');");
1129
1130     // Copy the document content to std::wstring and compare with the
1131     // expected result.
1132     const int kMaxOutputCharacters = 16;
1133     base::string16 output = GetMainFrame()->contentAsText(kMaxOutputCharacters);
1134     EXPECT_EQ(base::WideToUTF16(kTextDirection[i].expected_result), output);
1135   }
1136 }
1137
1138 // see http://crbug.com/238750
1139 #if defined(OS_WIN)
1140 #define MAYBE_OnHandleKeyboardEvent DISABLED_OnHandleKeyboardEvent
1141 #else
1142 #define MAYBE_OnHandleKeyboardEvent OnHandleKeyboardEvent
1143 #endif
1144
1145 // Test that we can receive correct DOM events when we send input events
1146 // through the RenderWidget::OnHandleInputEvent() function.
1147 TEST_F(RenderViewImplTest, MAYBE_OnHandleKeyboardEvent) {
1148 #if !defined(OS_MACOSX)
1149   // Load an HTML page consisting of one <input> element and three
1150   // contentediable <div> elements.
1151   // The <input> element is used for sending keyboard events, and the <div>
1152   // elements are used for writing DOM events in the following format:
1153   //   "<keyCode>,<shiftKey>,<controlKey>,<altKey>".
1154   // TODO(hbono): <http://crbug.com/2215> Our WebKit port set |ev.metaKey| to
1155   // true when pressing an alt key, i.e. the |ev.metaKey| value is not
1156   // trustworthy. We will check the |ev.metaKey| value when this issue is fixed.
1157   view()->set_send_content_state_immediately(true);
1158   LoadHTML("<html>"
1159            "<head>"
1160            "<title></title>"
1161            "<script type='text/javascript' language='javascript'>"
1162            "function OnKeyEvent(ev) {"
1163            "  var result = document.getElementById(ev.type);"
1164            "  result.innerText ="
1165            "      (ev.which || ev.keyCode) + ',' +"
1166            "      ev.shiftKey + ',' +"
1167            "      ev.ctrlKey + ',' +"
1168            "      ev.altKey;"
1169            "  return true;"
1170            "}"
1171            "</script>"
1172            "</head>"
1173            "<body>"
1174            "<input id='test' type='text'"
1175            "    onkeydown='return OnKeyEvent(event);'"
1176            "    onkeypress='return OnKeyEvent(event);'"
1177            "    onkeyup='return OnKeyEvent(event);'>"
1178            "</input>"
1179            "<div id='keydown' contenteditable='true'>"
1180            "</div>"
1181            "<div id='keypress' contenteditable='true'>"
1182            "</div>"
1183            "<div id='keyup' contenteditable='true'>"
1184            "</div>"
1185            "</body>"
1186            "</html>");
1187   ExecuteJavaScript("document.getElementById('test').focus();");
1188   render_thread_->sink().ClearMessages();
1189
1190   static const MockKeyboard::Layout kLayouts[] = {
1191 #if defined(OS_WIN)
1192     // Since we ignore the mock keyboard layout on Linux and instead just use
1193     // the screen's keyboard layout, these trivially pass. They are commented
1194     // out to avoid the illusion that they work.
1195     MockKeyboard::LAYOUT_ARABIC,
1196     MockKeyboard::LAYOUT_CANADIAN_FRENCH,
1197     MockKeyboard::LAYOUT_FRENCH,
1198     MockKeyboard::LAYOUT_HEBREW,
1199     MockKeyboard::LAYOUT_RUSSIAN,
1200 #endif
1201     MockKeyboard::LAYOUT_UNITED_STATES,
1202   };
1203
1204   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kLayouts); ++i) {
1205     // For each key code, we send three keyboard events.
1206     //  * we press only the key;
1207     //  * we press the key and a left-shift key, and;
1208     //  * we press the key and a right-alt (AltGr) key.
1209     // For each modifiers, we need a string used for formatting its expected
1210     // result. (See the above comment for its format.)
1211     static const struct {
1212       MockKeyboard::Modifiers modifiers;
1213       const char* expected_result;
1214     } kModifierData[] = {
1215       {MockKeyboard::NONE,       "false,false,false"},
1216       {MockKeyboard::LEFT_SHIFT, "true,false,false"},
1217 #if defined(OS_WIN)
1218       {MockKeyboard::RIGHT_ALT,  "false,false,true"},
1219 #endif
1220     };
1221
1222     MockKeyboard::Layout layout = kLayouts[i];
1223     for (size_t j = 0; j < ARRAYSIZE_UNSAFE(kModifierData); ++j) {
1224       // Virtual key codes used for this test.
1225       static const int kKeyCodes[] = {
1226         '0', '1', '2', '3', '4', '5', '6', '7',
1227         '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
1228         'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
1229         'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
1230         'W', 'X', 'Y', 'Z',
1231         ui::VKEY_OEM_1,
1232         ui::VKEY_OEM_PLUS,
1233         ui::VKEY_OEM_COMMA,
1234         ui::VKEY_OEM_MINUS,
1235         ui::VKEY_OEM_PERIOD,
1236         ui::VKEY_OEM_2,
1237         ui::VKEY_OEM_3,
1238         ui::VKEY_OEM_4,
1239         ui::VKEY_OEM_5,
1240         ui::VKEY_OEM_6,
1241         ui::VKEY_OEM_7,
1242 #if defined(OS_WIN)
1243         // Not sure how to handle this key on Linux.
1244         ui::VKEY_OEM_8,
1245 #endif
1246       };
1247
1248       MockKeyboard::Modifiers modifiers = kModifierData[j].modifiers;
1249       for (size_t k = 0; k < ARRAYSIZE_UNSAFE(kKeyCodes); ++k) {
1250         // Send a keyboard event to the RenderView object.
1251         // We should test a keyboard event only when the given keyboard-layout
1252         // driver is installed in a PC and the driver can assign a Unicode
1253         // charcter for the given tuple (key-code and modifiers).
1254         int key_code = kKeyCodes[k];
1255         base::string16 char_code;
1256         if (SendKeyEvent(layout, key_code, modifiers, &char_code) < 0)
1257           continue;
1258
1259         // Create an expected result from the virtual-key code, the character
1260         // code, and the modifier-key status.
1261         // We format a string that emulates a DOM-event string produced hy
1262         // our JavaScript function. (See the above comment for the format.)
1263         static char expected_result[1024];
1264         expected_result[0] = 0;
1265         base::snprintf(&expected_result[0],
1266                        sizeof(expected_result),
1267                        "\n"       // texts in the <input> element
1268                        "%d,%s\n"  // texts in the first <div> element
1269                        "%d,%s\n"  // texts in the second <div> element
1270                        "%d,%s",   // texts in the third <div> element
1271                        key_code, kModifierData[j].expected_result,
1272                        static_cast<int>(char_code[0]),
1273                        kModifierData[j].expected_result,
1274                        key_code, kModifierData[j].expected_result);
1275
1276         // Retrieve the text in the test page and compare it with the expected
1277         // text created from a virtual-key code, a character code, and the
1278         // modifier-key status.
1279         const int kMaxOutputCharacters = 1024;
1280         std::string output = base::UTF16ToUTF8(
1281             GetMainFrame()->contentAsText(kMaxOutputCharacters));
1282         EXPECT_EQ(expected_result, output);
1283       }
1284     }
1285   }
1286 #else
1287   NOTIMPLEMENTED();
1288 #endif
1289 }
1290
1291 // Test that our EditorClientImpl class can insert characters when we send
1292 // keyboard events through the RenderWidget::OnHandleInputEvent() function.
1293 // This test is for preventing regressions caused only when we use non-US
1294 // keyboards, such as Issue 10846.
1295 // see http://crbug.com/244562
1296 #if defined(OS_WIN)
1297 #define MAYBE_InsertCharacters DISABLED_InsertCharacters
1298 #else
1299 #define MAYBE_InsertCharacters InsertCharacters
1300 #endif
1301 TEST_F(RenderViewImplTest, MAYBE_InsertCharacters) {
1302 #if !defined(OS_MACOSX)
1303   static const struct {
1304     MockKeyboard::Layout layout;
1305     const wchar_t* expected_result;
1306   } kLayouts[] = {
1307 #if 0
1308     // Disabled these keyboard layouts because buildbots do not have their
1309     // keyboard-layout drivers installed.
1310     {MockKeyboard::LAYOUT_ARABIC,
1311      L"\x0030\x0031\x0032\x0033\x0034\x0035\x0036\x0037"
1312      L"\x0038\x0039\x0634\x0624\x064a\x062b\x0628\x0644"
1313      L"\x0627\x0647\x062a\x0646\x0645\x0629\x0649\x062e"
1314      L"\x062d\x0636\x0642\x0633\x0641\x0639\x0631\x0635"
1315      L"\x0621\x063a\x0626\x0643\x003d\x0648\x002d\x0632"
1316      L"\x0638\x0630\x062c\x005c\x062f\x0637\x0028\x0021"
1317      L"\x0040\x0023\x0024\x0025\x005e\x0026\x002a\x0029"
1318      L"\x0650\x007d\x005d\x064f\x005b\x0623\x00f7\x0640"
1319      L"\x060c\x002f\x2019\x0622\x00d7\x061b\x064e\x064c"
1320      L"\x064d\x2018\x007b\x064b\x0652\x0625\x007e\x003a"
1321      L"\x002b\x002c\x005f\x002e\x061f\x0651\x003c\x007c"
1322      L"\x003e\x0022\x0030\x0031\x0032\x0033\x0034\x0035"
1323      L"\x0036\x0037\x0038\x0039\x0634\x0624\x064a\x062b"
1324      L"\x0628\x0644\x0627\x0647\x062a\x0646\x0645\x0629"
1325      L"\x0649\x062e\x062d\x0636\x0642\x0633\x0641\x0639"
1326      L"\x0631\x0635\x0621\x063a\x0626\x0643\x003d\x0648"
1327      L"\x002d\x0632\x0638\x0630\x062c\x005c\x062f\x0637"
1328     },
1329     {MockKeyboard::LAYOUT_HEBREW,
1330      L"\x0030\x0031\x0032\x0033\x0034\x0035\x0036\x0037"
1331      L"\x0038\x0039\x05e9\x05e0\x05d1\x05d2\x05e7\x05db"
1332      L"\x05e2\x05d9\x05df\x05d7\x05dc\x05da\x05e6\x05de"
1333      L"\x05dd\x05e4\x002f\x05e8\x05d3\x05d0\x05d5\x05d4"
1334      L"\x0027\x05e1\x05d8\x05d6\x05e3\x003d\x05ea\x002d"
1335      L"\x05e5\x002e\x003b\x005d\x005c\x005b\x002c\x0028"
1336      L"\x0021\x0040\x0023\x0024\x0025\x005e\x0026\x002a"
1337      L"\x0029\x0041\x0042\x0043\x0044\x0045\x0046\x0047"
1338      L"\x0048\x0049\x004a\x004b\x004c\x004d\x004e\x004f"
1339      L"\x0050\x0051\x0052\x0053\x0054\x0055\x0056\x0057"
1340      L"\x0058\x0059\x005a\x003a\x002b\x003e\x005f\x003c"
1341      L"\x003f\x007e\x007d\x007c\x007b\x0022\x0030\x0031"
1342      L"\x0032\x0033\x0034\x0035\x0036\x0037\x0038\x0039"
1343      L"\x05e9\x05e0\x05d1\x05d2\x05e7\x05db\x05e2\x05d9"
1344      L"\x05df\x05d7\x05dc\x05da\x05e6\x05de\x05dd\x05e4"
1345      L"\x002f\x05e8\x05d3\x05d0\x05d5\x05d4\x0027\x05e1"
1346      L"\x05d8\x05d6\x05e3\x003d\x05ea\x002d\x05e5\x002e"
1347      L"\x003b\x005d\x005c\x005b\x002c"
1348     },
1349 #endif
1350 #if defined(OS_WIN)
1351     // On Linux, the only way to test alternate keyboard layouts is to change
1352     // the keyboard layout of the whole screen. I'm worried about the side
1353     // effects this may have on the buildbots.
1354     {MockKeyboard::LAYOUT_CANADIAN_FRENCH,
1355      L"\x0030\x0031\x0032\x0033\x0034\x0035\x0036\x0037"
1356      L"\x0038\x0039\x0061\x0062\x0063\x0064\x0065\x0066"
1357      L"\x0067\x0068\x0069\x006a\x006b\x006c\x006d\x006e"
1358      L"\x006f\x0070\x0071\x0072\x0073\x0074\x0075\x0076"
1359      L"\x0077\x0078\x0079\x007a\x003b\x003d\x002c\x002d"
1360      L"\x002e\x00e9\x003c\x0029\x0021\x0022\x002f\x0024"
1361      L"\x0025\x003f\x0026\x002a\x0028\x0041\x0042\x0043"
1362      L"\x0044\x0045\x0046\x0047\x0048\x0049\x004a\x004b"
1363      L"\x004c\x004d\x004e\x004f\x0050\x0051\x0052\x0053"
1364      L"\x0054\x0055\x0056\x0057\x0058\x0059\x005a\x003a"
1365      L"\x002b\x0027\x005f\x002e\x00c9\x003e\x0030\x0031"
1366      L"\x0032\x0033\x0034\x0035\x0036\x0037\x0038\x0039"
1367      L"\x0061\x0062\x0063\x0064\x0065\x0066\x0067\x0068"
1368      L"\x0069\x006a\x006b\x006c\x006d\x006e\x006f\x0070"
1369      L"\x0071\x0072\x0073\x0074\x0075\x0076\x0077\x0078"
1370      L"\x0079\x007a\x003b\x003d\x002c\x002d\x002e\x00e9"
1371      L"\x003c"
1372     },
1373     {MockKeyboard::LAYOUT_FRENCH,
1374      L"\x00e0\x0026\x00e9\x0022\x0027\x0028\x002d\x00e8"
1375      L"\x005f\x00e7\x0061\x0062\x0063\x0064\x0065\x0066"
1376      L"\x0067\x0068\x0069\x006a\x006b\x006c\x006d\x006e"
1377      L"\x006f\x0070\x0071\x0072\x0073\x0074\x0075\x0076"
1378      L"\x0077\x0078\x0079\x007a\x0024\x003d\x002c\x003b"
1379      L"\x003a\x00f9\x0029\x002a\x0021\x0030\x0031\x0032"
1380      L"\x0033\x0034\x0035\x0036\x0037\x0038\x0039\x0041"
1381      L"\x0042\x0043\x0044\x0045\x0046\x0047\x0048\x0049"
1382      L"\x004a\x004b\x004c\x004d\x004e\x004f\x0050\x0051"
1383      L"\x0052\x0053\x0054\x0055\x0056\x0057\x0058\x0059"
1384      L"\x005a\x00a3\x002b\x003f\x002e\x002f\x0025\x00b0"
1385      L"\x00b5\x00e0\x0026\x00e9\x0022\x0027\x0028\x002d"
1386      L"\x00e8\x005f\x00e7\x0061\x0062\x0063\x0064\x0065"
1387      L"\x0066\x0067\x0068\x0069\x006a\x006b\x006c\x006d"
1388      L"\x006e\x006f\x0070\x0071\x0072\x0073\x0074\x0075"
1389      L"\x0076\x0077\x0078\x0079\x007a\x0024\x003d\x002c"
1390      L"\x003b\x003a\x00f9\x0029\x002a\x0021"
1391     },
1392     {MockKeyboard::LAYOUT_RUSSIAN,
1393      L"\x0030\x0031\x0032\x0033\x0034\x0035\x0036\x0037"
1394      L"\x0038\x0039\x0444\x0438\x0441\x0432\x0443\x0430"
1395      L"\x043f\x0440\x0448\x043e\x043b\x0434\x044c\x0442"
1396      L"\x0449\x0437\x0439\x043a\x044b\x0435\x0433\x043c"
1397      L"\x0446\x0447\x043d\x044f\x0436\x003d\x0431\x002d"
1398      L"\x044e\x002e\x0451\x0445\x005c\x044a\x044d\x0029"
1399      L"\x0021\x0022\x2116\x003b\x0025\x003a\x003f\x002a"
1400      L"\x0028\x0424\x0418\x0421\x0412\x0423\x0410\x041f"
1401      L"\x0420\x0428\x041e\x041b\x0414\x042c\x0422\x0429"
1402      L"\x0417\x0419\x041a\x042b\x0415\x0413\x041c\x0426"
1403      L"\x0427\x041d\x042f\x0416\x002b\x0411\x005f\x042e"
1404      L"\x002c\x0401\x0425\x002f\x042a\x042d\x0030\x0031"
1405      L"\x0032\x0033\x0034\x0035\x0036\x0037\x0038\x0039"
1406      L"\x0444\x0438\x0441\x0432\x0443\x0430\x043f\x0440"
1407      L"\x0448\x043e\x043b\x0434\x044c\x0442\x0449\x0437"
1408      L"\x0439\x043a\x044b\x0435\x0433\x043c\x0446\x0447"
1409      L"\x043d\x044f\x0436\x003d\x0431\x002d\x044e\x002e"
1410      L"\x0451\x0445\x005c\x044a\x044d"
1411     },
1412 #endif  // defined(OS_WIN)
1413     {MockKeyboard::LAYOUT_UNITED_STATES,
1414      L"\x0030\x0031\x0032\x0033\x0034\x0035\x0036\x0037"
1415      L"\x0038\x0039\x0061\x0062\x0063\x0064\x0065\x0066"
1416      L"\x0067\x0068\x0069\x006a\x006b\x006c\x006d\x006e"
1417      L"\x006f\x0070\x0071\x0072\x0073\x0074\x0075\x0076"
1418      L"\x0077\x0078\x0079\x007a\x003b\x003d\x002c\x002d"
1419      L"\x002e\x002f\x0060\x005b\x005c\x005d\x0027\x0029"
1420      L"\x0021\x0040\x0023\x0024\x0025\x005e\x0026\x002a"
1421      L"\x0028\x0041\x0042\x0043\x0044\x0045\x0046\x0047"
1422      L"\x0048\x0049\x004a\x004b\x004c\x004d\x004e\x004f"
1423      L"\x0050\x0051\x0052\x0053\x0054\x0055\x0056\x0057"
1424      L"\x0058\x0059\x005a\x003a\x002b\x003c\x005f\x003e"
1425      L"\x003f\x007e\x007b\x007c\x007d\x0022"
1426 #if defined(OS_WIN)
1427      // This is ifdefed out for Linux to correspond to the fact that we don't
1428      // test alt+keystroke for now.
1429      L"\x0030\x0031\x0032\x0033\x0034\x0035\x0036\x0037"
1430      L"\x0038\x0039\x0061\x0062\x0063\x0064\x0065\x0066"
1431      L"\x0067\x0068\x0069\x006a\x006b\x006c\x006d\x006e"
1432      L"\x006f\x0070\x0071\x0072\x0073\x0074\x0075\x0076"
1433      L"\x0077\x0078\x0079\x007a\x003b\x003d\x002c\x002d"
1434      L"\x002e\x002f\x0060\x005b\x005c\x005d\x0027"
1435 #endif
1436     },
1437   };
1438
1439   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kLayouts); ++i) {
1440     // Load an HTML page consisting of one <div> element.
1441     // This <div> element is used by the EditorClientImpl class to insert
1442     // characters received through the RenderWidget::OnHandleInputEvent()
1443     // function.
1444     view()->set_send_content_state_immediately(true);
1445     LoadHTML("<html>"
1446              "<head>"
1447              "<title></title>"
1448              "</head>"
1449              "<body>"
1450              "<div id='test' contenteditable='true'>"
1451              "</div>"
1452              "</body>"
1453              "</html>");
1454     ExecuteJavaScript("document.getElementById('test').focus();");
1455     render_thread_->sink().ClearMessages();
1456
1457     // For each key code, we send three keyboard events.
1458     //  * Pressing only the key;
1459     //  * Pressing the key and a left-shift key, and;
1460     //  * Pressing the key and a right-alt (AltGr) key.
1461     static const MockKeyboard::Modifiers kModifiers[] = {
1462       MockKeyboard::NONE,
1463       MockKeyboard::LEFT_SHIFT,
1464 #if defined(OS_WIN)
1465       MockKeyboard::RIGHT_ALT,
1466 #endif
1467     };
1468
1469     MockKeyboard::Layout layout = kLayouts[i].layout;
1470     for (size_t j = 0; j < ARRAYSIZE_UNSAFE(kModifiers); ++j) {
1471       // Virtual key codes used for this test.
1472       static const int kKeyCodes[] = {
1473         '0', '1', '2', '3', '4', '5', '6', '7',
1474         '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
1475         'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
1476         'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
1477         'W', 'X', 'Y', 'Z',
1478         ui::VKEY_OEM_1,
1479         ui::VKEY_OEM_PLUS,
1480         ui::VKEY_OEM_COMMA,
1481         ui::VKEY_OEM_MINUS,
1482         ui::VKEY_OEM_PERIOD,
1483         ui::VKEY_OEM_2,
1484         ui::VKEY_OEM_3,
1485         ui::VKEY_OEM_4,
1486         ui::VKEY_OEM_5,
1487         ui::VKEY_OEM_6,
1488         ui::VKEY_OEM_7,
1489 #if defined(OS_WIN)
1490         // Unclear how to handle this on Linux.
1491         ui::VKEY_OEM_8,
1492 #endif
1493       };
1494
1495       MockKeyboard::Modifiers modifiers = kModifiers[j];
1496       for (size_t k = 0; k < ARRAYSIZE_UNSAFE(kKeyCodes); ++k) {
1497         // Send a keyboard event to the RenderView object.
1498         // We should test a keyboard event only when the given keyboard-layout
1499         // driver is installed in a PC and the driver can assign a Unicode
1500         // charcter for the given tuple (layout, key-code, and modifiers).
1501         int key_code = kKeyCodes[k];
1502         base::string16 char_code;
1503         if (SendKeyEvent(layout, key_code, modifiers, &char_code) < 0)
1504           continue;
1505       }
1506     }
1507
1508     // Retrieve the text in the test page and compare it with the expected
1509     // text created from a virtual-key code, a character code, and the
1510     // modifier-key status.
1511     const int kMaxOutputCharacters = 4096;
1512     base::string16 output = GetMainFrame()->contentAsText(kMaxOutputCharacters);
1513     EXPECT_EQ(base::WideToUTF16(kLayouts[i].expected_result), output);
1514   }
1515 #else
1516   NOTIMPLEMENTED();
1517 #endif
1518 }
1519
1520 // Crashy, http://crbug.com/53247.
1521 TEST_F(RenderViewImplTest, DISABLED_DidFailProvisionalLoadWithErrorForError) {
1522   GetMainFrame()->enableViewSourceMode(true);
1523   WebURLError error;
1524   error.domain = WebString::fromUTF8(net::kErrorDomain);
1525   error.reason = net::ERR_FILE_NOT_FOUND;
1526   error.unreachableURL = GURL("http://foo");
1527   WebLocalFrame* web_frame = GetMainFrame();
1528
1529   // Start a load that will reach provisional state synchronously,
1530   // but won't complete synchronously.
1531   FrameMsg_Navigate_Params params;
1532   params.page_id = -1;
1533   params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
1534   params.url = GURL("data:text/html,test data");
1535   frame()->OnNavigate(params);
1536
1537   // An error occurred.
1538   view()->main_render_frame()->didFailProvisionalLoad(web_frame, error);
1539   // Frame should exit view-source mode.
1540   EXPECT_FALSE(web_frame->isViewSourceModeEnabled());
1541 }
1542
1543 TEST_F(RenderViewImplTest, DidFailProvisionalLoadWithErrorForCancellation) {
1544   GetMainFrame()->enableViewSourceMode(true);
1545   WebURLError error;
1546   error.domain = WebString::fromUTF8(net::kErrorDomain);
1547   error.reason = net::ERR_ABORTED;
1548   error.unreachableURL = GURL("http://foo");
1549   WebLocalFrame* web_frame = GetMainFrame();
1550
1551   // Start a load that will reach provisional state synchronously,
1552   // but won't complete synchronously.
1553   FrameMsg_Navigate_Params params;
1554   params.page_id = -1;
1555   params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
1556   params.url = GURL("data:text/html,test data");
1557   frame()->OnNavigate(params);
1558
1559   // A cancellation occurred.
1560   view()->main_render_frame()->didFailProvisionalLoad(web_frame, error);
1561   // Frame should stay in view-source mode.
1562   EXPECT_TRUE(web_frame->isViewSourceModeEnabled());
1563 }
1564
1565 // Regression test for http://crbug.com/41562
1566 TEST_F(RenderViewImplTest, UpdateTargetURLWithInvalidURL) {
1567   const GURL invalid_gurl("http://");
1568   view()->setMouseOverURL(blink::WebURL(invalid_gurl));
1569   EXPECT_EQ(invalid_gurl, view()->target_url_);
1570 }
1571
1572 TEST_F(RenderViewImplTest, SetHistoryLengthAndPrune) {
1573   int expected_page_id = -1;
1574
1575   // No history to merge and no committed pages.
1576   view()->OnSetHistoryLengthAndPrune(0, -1);
1577   EXPECT_EQ(0, view()->history_list_length_);
1578   EXPECT_EQ(-1, view()->history_list_offset_);
1579
1580   // History to merge and no committed pages.
1581   view()->OnSetHistoryLengthAndPrune(2, -1);
1582   EXPECT_EQ(2, view()->history_list_length_);
1583   EXPECT_EQ(1, view()->history_list_offset_);
1584   EXPECT_EQ(-1, view()->history_page_ids_[0]);
1585   EXPECT_EQ(-1, view()->history_page_ids_[1]);
1586   ClearHistory();
1587
1588   blink::WebHistoryItem item;
1589   item.initialize();
1590
1591   // No history to merge and a committed page to be kept.
1592   frame()->didCommitProvisionalLoad(GetMainFrame(),
1593                                     item,
1594                                     blink::WebStandardCommit);
1595   expected_page_id = view()->page_id_;
1596   view()->OnSetHistoryLengthAndPrune(0, expected_page_id);
1597   EXPECT_EQ(1, view()->history_list_length_);
1598   EXPECT_EQ(0, view()->history_list_offset_);
1599   EXPECT_EQ(expected_page_id, view()->history_page_ids_[0]);
1600   ClearHistory();
1601
1602   // No history to merge and a committed page to be pruned.
1603   frame()->didCommitProvisionalLoad(GetMainFrame(),
1604                                     item,
1605                                     blink::WebStandardCommit);
1606   expected_page_id = view()->page_id_;
1607   view()->OnSetHistoryLengthAndPrune(0, expected_page_id + 1);
1608   EXPECT_EQ(0, view()->history_list_length_);
1609   EXPECT_EQ(-1, view()->history_list_offset_);
1610   ClearHistory();
1611
1612   // No history to merge and a committed page that the browser was unaware of.
1613   frame()->didCommitProvisionalLoad(GetMainFrame(),
1614                                     item,
1615                                     blink::WebStandardCommit);
1616   expected_page_id = view()->page_id_;
1617   view()->OnSetHistoryLengthAndPrune(0, -1);
1618   EXPECT_EQ(1, view()->history_list_length_);
1619   EXPECT_EQ(0, view()->history_list_offset_);
1620   EXPECT_EQ(expected_page_id, view()->history_page_ids_[0]);
1621   ClearHistory();
1622
1623   // History to merge and a committed page to be kept.
1624   frame()->didCommitProvisionalLoad(GetMainFrame(),
1625                                     item,
1626                                     blink::WebStandardCommit);
1627   expected_page_id = view()->page_id_;
1628   view()->OnSetHistoryLengthAndPrune(2, expected_page_id);
1629   EXPECT_EQ(3, view()->history_list_length_);
1630   EXPECT_EQ(2, view()->history_list_offset_);
1631   EXPECT_EQ(-1, view()->history_page_ids_[0]);
1632   EXPECT_EQ(-1, view()->history_page_ids_[1]);
1633   EXPECT_EQ(expected_page_id, view()->history_page_ids_[2]);
1634   ClearHistory();
1635
1636   // History to merge and a committed page to be pruned.
1637   frame()->didCommitProvisionalLoad(GetMainFrame(),
1638                                     item,
1639                                     blink::WebStandardCommit);
1640   expected_page_id = view()->page_id_;
1641   view()->OnSetHistoryLengthAndPrune(2, expected_page_id + 1);
1642   EXPECT_EQ(2, view()->history_list_length_);
1643   EXPECT_EQ(1, view()->history_list_offset_);
1644   EXPECT_EQ(-1, view()->history_page_ids_[0]);
1645   EXPECT_EQ(-1, view()->history_page_ids_[1]);
1646   ClearHistory();
1647
1648   // History to merge and a committed page that the browser was unaware of.
1649   frame()->didCommitProvisionalLoad(GetMainFrame(),
1650                                     item,
1651                                     blink::WebStandardCommit);
1652   expected_page_id = view()->page_id_;
1653   view()->OnSetHistoryLengthAndPrune(2, -1);
1654   EXPECT_EQ(3, view()->history_list_length_);
1655   EXPECT_EQ(2, view()->history_list_offset_);
1656   EXPECT_EQ(-1, view()->history_page_ids_[0]);
1657   EXPECT_EQ(-1, view()->history_page_ids_[1]);
1658   EXPECT_EQ(expected_page_id, view()->history_page_ids_[2]);
1659   ClearHistory();
1660
1661   int expected_page_id_2 = -1;
1662
1663   // No history to merge and two committed pages, both to be kept.
1664   frame()->didCommitProvisionalLoad(GetMainFrame(),
1665                                     item,
1666                                     blink::WebStandardCommit);
1667   expected_page_id = view()->page_id_;
1668   frame()->didCommitProvisionalLoad(GetMainFrame(),
1669                                     item,
1670                                     blink::WebStandardCommit);
1671   expected_page_id_2 = view()->page_id_;
1672   EXPECT_GT(expected_page_id_2, expected_page_id);
1673   view()->OnSetHistoryLengthAndPrune(0, expected_page_id);
1674   EXPECT_EQ(2, view()->history_list_length_);
1675   EXPECT_EQ(1, view()->history_list_offset_);
1676   EXPECT_EQ(expected_page_id, view()->history_page_ids_[0]);
1677   EXPECT_EQ(expected_page_id_2, view()->history_page_ids_[1]);
1678   ClearHistory();
1679
1680   // No history to merge and two committed pages, and only the second is kept.
1681   frame()->didCommitProvisionalLoad(GetMainFrame(),
1682                                     item,
1683                                     blink::WebStandardCommit);
1684   expected_page_id = view()->page_id_;
1685   frame()->didCommitProvisionalLoad(GetMainFrame(),
1686                                     item,
1687                                     blink::WebStandardCommit);
1688   expected_page_id_2 = view()->page_id_;
1689   EXPECT_GT(expected_page_id_2, expected_page_id);
1690   view()->OnSetHistoryLengthAndPrune(0, expected_page_id_2);
1691   EXPECT_EQ(1, view()->history_list_length_);
1692   EXPECT_EQ(0, view()->history_list_offset_);
1693   EXPECT_EQ(expected_page_id_2, view()->history_page_ids_[0]);
1694   ClearHistory();
1695
1696   // No history to merge and two committed pages, both of which the browser was
1697   // unaware of.
1698   frame()->didCommitProvisionalLoad(GetMainFrame(),
1699                                     item,
1700                                     blink::WebStandardCommit);
1701   expected_page_id = view()->page_id_;
1702   frame()->didCommitProvisionalLoad(GetMainFrame(),
1703                                     item,
1704                                     blink::WebStandardCommit);
1705   expected_page_id_2 = view()->page_id_;
1706   EXPECT_GT(expected_page_id_2, expected_page_id);
1707   view()->OnSetHistoryLengthAndPrune(0, -1);
1708   EXPECT_EQ(2, view()->history_list_length_);
1709   EXPECT_EQ(1, view()->history_list_offset_);
1710   EXPECT_EQ(expected_page_id, view()->history_page_ids_[0]);
1711   EXPECT_EQ(expected_page_id_2, view()->history_page_ids_[1]);
1712   ClearHistory();
1713
1714   // History to merge and two committed pages, both to be kept.
1715   frame()->didCommitProvisionalLoad(GetMainFrame(),
1716                                     item,
1717                                     blink::WebStandardCommit);
1718   expected_page_id = view()->page_id_;
1719   frame()->didCommitProvisionalLoad(GetMainFrame(),
1720                                     item,
1721                                     blink::WebStandardCommit);
1722   expected_page_id_2 = view()->page_id_;
1723   EXPECT_GT(expected_page_id_2, expected_page_id);
1724   view()->OnSetHistoryLengthAndPrune(2, expected_page_id);
1725   EXPECT_EQ(4, view()->history_list_length_);
1726   EXPECT_EQ(3, view()->history_list_offset_);
1727   EXPECT_EQ(-1, view()->history_page_ids_[0]);
1728   EXPECT_EQ(-1, view()->history_page_ids_[1]);
1729   EXPECT_EQ(expected_page_id, view()->history_page_ids_[2]);
1730   EXPECT_EQ(expected_page_id_2, view()->history_page_ids_[3]);
1731   ClearHistory();
1732
1733   // History to merge and two committed pages, and only the second is kept.
1734   frame()->didCommitProvisionalLoad(GetMainFrame(),
1735                                     item,
1736                                     blink::WebStandardCommit);
1737   expected_page_id = view()->page_id_;
1738   frame()->didCommitProvisionalLoad(GetMainFrame(),
1739                                     item,
1740                                     blink::WebStandardCommit);
1741   expected_page_id_2 = view()->page_id_;
1742   EXPECT_GT(expected_page_id_2, expected_page_id);
1743   view()->OnSetHistoryLengthAndPrune(2, expected_page_id_2);
1744   EXPECT_EQ(3, view()->history_list_length_);
1745   EXPECT_EQ(2, view()->history_list_offset_);
1746   EXPECT_EQ(-1, view()->history_page_ids_[0]);
1747   EXPECT_EQ(-1, view()->history_page_ids_[1]);
1748   EXPECT_EQ(expected_page_id_2, view()->history_page_ids_[2]);
1749   ClearHistory();
1750
1751   // History to merge and two committed pages, both of which the browser was
1752   // unaware of.
1753   frame()->didCommitProvisionalLoad(GetMainFrame(),
1754                                     item,
1755                                     blink::WebStandardCommit);
1756   expected_page_id = view()->page_id_;
1757   frame()->didCommitProvisionalLoad(GetMainFrame(),
1758                                     item,
1759                                     blink::WebStandardCommit);
1760   expected_page_id_2 = view()->page_id_;
1761   EXPECT_GT(expected_page_id_2, expected_page_id);
1762   view()->OnSetHistoryLengthAndPrune(2, -1);
1763   EXPECT_EQ(4, view()->history_list_length_);
1764   EXPECT_EQ(3, view()->history_list_offset_);
1765   EXPECT_EQ(-1, view()->history_page_ids_[0]);
1766   EXPECT_EQ(-1, view()->history_page_ids_[1]);
1767   EXPECT_EQ(expected_page_id, view()->history_page_ids_[2]);
1768   EXPECT_EQ(expected_page_id_2, view()->history_page_ids_[3]);
1769 }
1770
1771 TEST_F(RenderViewImplTest, ContextMenu) {
1772   LoadHTML("<div>Page A</div>");
1773
1774   // Create a right click in the center of the iframe. (I'm hoping this will
1775   // make this a bit more robust in case of some other formatting or other bug.)
1776   WebMouseEvent mouse_event;
1777   mouse_event.type = WebInputEvent::MouseDown;
1778   mouse_event.button = WebMouseEvent::ButtonRight;
1779   mouse_event.x = 250;
1780   mouse_event.y = 250;
1781   mouse_event.globalX = 250;
1782   mouse_event.globalY = 250;
1783
1784   SendWebMouseEvent(mouse_event);
1785
1786   // Now simulate the corresponding up event which should display the menu
1787   mouse_event.type = WebInputEvent::MouseUp;
1788   SendWebMouseEvent(mouse_event);
1789
1790   EXPECT_TRUE(render_thread_->sink().GetUniqueMessageMatching(
1791       FrameHostMsg_ContextMenu::ID));
1792 }
1793
1794 TEST_F(RenderViewImplTest, TestBackForward) {
1795   LoadHTML("<div id=pagename>Page A</div>");
1796   PageState page_a_state =
1797       HistoryEntryToPageState(view()->history_controller()->GetCurrentEntry());
1798   int was_page_a = -1;
1799   base::string16 check_page_a =
1800       base::ASCIIToUTF16(
1801           "Number(document.getElementById('pagename').innerHTML == 'Page A')");
1802   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_a, &was_page_a));
1803   EXPECT_EQ(1, was_page_a);
1804
1805   LoadHTML("<div id=pagename>Page B</div>");
1806   int was_page_b = -1;
1807   base::string16 check_page_b =
1808       base::ASCIIToUTF16(
1809           "Number(document.getElementById('pagename').innerHTML == 'Page B')");
1810   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_b, &was_page_b));
1811   EXPECT_EQ(1, was_page_b);
1812
1813   PageState back_state =
1814       HistoryEntryToPageState(view()->history_controller()->GetCurrentEntry());
1815
1816   LoadHTML("<div id=pagename>Page C</div>");
1817   int was_page_c = -1;
1818   base::string16 check_page_c =
1819       base::ASCIIToUTF16(
1820           "Number(document.getElementById('pagename').innerHTML == 'Page C')");
1821   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_c, &was_page_c));
1822   EXPECT_EQ(1, was_page_b);
1823
1824   PageState forward_state =
1825       HistoryEntryToPageState(view()->history_controller()->GetCurrentEntry());
1826   GoBack(back_state);
1827   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_b, &was_page_b));
1828   EXPECT_EQ(1, was_page_b);
1829
1830   PageState back_state2 =
1831       HistoryEntryToPageState(view()->history_controller()->GetCurrentEntry());
1832
1833   GoForward(forward_state);
1834   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_c, &was_page_c));
1835   EXPECT_EQ(1, was_page_c);
1836
1837   GoBack(back_state2);
1838   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_b, &was_page_b));
1839   EXPECT_EQ(1, was_page_b);
1840
1841   forward_state =
1842       HistoryEntryToPageState(view()->history_controller()->GetCurrentEntry());
1843   GoBack(page_a_state);
1844   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_a, &was_page_a));
1845   EXPECT_EQ(1, was_page_a);
1846
1847   GoForward(forward_state);
1848   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_b, &was_page_b));
1849   EXPECT_EQ(1, was_page_b);
1850 }
1851
1852 #if defined(OS_MACOSX) || defined(USE_AURA)
1853 TEST_F(RenderViewImplTest, GetCompositionCharacterBoundsTest) {
1854
1855 #if defined(OS_WIN)
1856   // http://crbug.com/304193
1857   if (base::win::GetVersion() < base::win::VERSION_VISTA)
1858     return;
1859 #endif
1860
1861   LoadHTML("<textarea id=\"test\"></textarea>");
1862   ExecuteJavaScript("document.getElementById('test').focus();");
1863
1864   const base::string16 empty_string;
1865   const std::vector<blink::WebCompositionUnderline> empty_underline;
1866   std::vector<gfx::Rect> bounds;
1867   view()->OnSetFocus(true);
1868   view()->OnSetInputMethodActive(true);
1869
1870   // ASCII composition
1871   const base::string16 ascii_composition = base::UTF8ToUTF16("aiueo");
1872   view()->OnImeSetComposition(ascii_composition, empty_underline, 0, 0);
1873   view()->GetCompositionCharacterBounds(&bounds);
1874   ASSERT_EQ(ascii_composition.size(), bounds.size());
1875   for (size_t i = 0; i < bounds.size(); ++i)
1876     EXPECT_LT(0, bounds[i].width());
1877   view()->OnImeConfirmComposition(
1878       empty_string, gfx::Range::InvalidRange(), false);
1879
1880   // Non surrogate pair unicode character.
1881   const base::string16 unicode_composition = base::UTF8ToUTF16(
1882       "\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86\xE3\x81\x88\xE3\x81\x8A");
1883   view()->OnImeSetComposition(unicode_composition, empty_underline, 0, 0);
1884   view()->GetCompositionCharacterBounds(&bounds);
1885   ASSERT_EQ(unicode_composition.size(), bounds.size());
1886   for (size_t i = 0; i < bounds.size(); ++i)
1887     EXPECT_LT(0, bounds[i].width());
1888   view()->OnImeConfirmComposition(
1889       empty_string, gfx::Range::InvalidRange(), false);
1890
1891   // Surrogate pair character.
1892   const base::string16 surrogate_pair_char =
1893       base::UTF8ToUTF16("\xF0\xA0\xAE\x9F");
1894   view()->OnImeSetComposition(surrogate_pair_char,
1895                               empty_underline,
1896                               0,
1897                               0);
1898   view()->GetCompositionCharacterBounds(&bounds);
1899   ASSERT_EQ(surrogate_pair_char.size(), bounds.size());
1900   EXPECT_LT(0, bounds[0].width());
1901   EXPECT_EQ(0, bounds[1].width());
1902   view()->OnImeConfirmComposition(
1903       empty_string, gfx::Range::InvalidRange(), false);
1904
1905   // Mixed string.
1906   const base::string16 surrogate_pair_mixed_composition =
1907       surrogate_pair_char + base::UTF8ToUTF16("\xE3\x81\x82") +
1908       surrogate_pair_char + base::UTF8ToUTF16("b") + surrogate_pair_char;
1909   const size_t utf16_length = 8UL;
1910   const bool is_surrogate_pair_empty_rect[8] = {
1911     false, true, false, false, true, false, false, true };
1912   view()->OnImeSetComposition(surrogate_pair_mixed_composition,
1913                               empty_underline,
1914                               0,
1915                               0);
1916   view()->GetCompositionCharacterBounds(&bounds);
1917   ASSERT_EQ(utf16_length, bounds.size());
1918   for (size_t i = 0; i < utf16_length; ++i) {
1919     if (is_surrogate_pair_empty_rect[i]) {
1920       EXPECT_EQ(0, bounds[i].width());
1921     } else {
1922       EXPECT_LT(0, bounds[i].width());
1923     }
1924   }
1925   view()->OnImeConfirmComposition(
1926       empty_string, gfx::Range::InvalidRange(), false);
1927 }
1928 #endif
1929
1930 TEST_F(RenderViewImplTest, ZoomLimit) {
1931   const double kMinZoomLevel = ZoomFactorToZoomLevel(kMinimumZoomFactor);
1932   const double kMaxZoomLevel = ZoomFactorToZoomLevel(kMaximumZoomFactor);
1933
1934   FrameMsg_Navigate_Params params;
1935   params.page_id = -1;
1936   params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
1937
1938   // Verifies navigation to a URL with preset zoom level indeed sets the level.
1939   // Regression test for http://crbug.com/139559, where the level was not
1940   // properly set when it is out of the default zoom limits of WebView.
1941   params.url = GURL("data:text/html,min_zoomlimit_test");
1942   view()->OnSetZoomLevelForLoadingURL(params.url, kMinZoomLevel);
1943   frame()->OnNavigate(params);
1944   ProcessPendingMessages();
1945   EXPECT_DOUBLE_EQ(kMinZoomLevel, view()->GetWebView()->zoomLevel());
1946
1947   // It should work even when the zoom limit is temporarily changed in the page.
1948   view()->GetWebView()->zoomLimitsChanged(ZoomFactorToZoomLevel(1.0),
1949                                           ZoomFactorToZoomLevel(1.0));
1950   params.url = GURL("data:text/html,max_zoomlimit_test");
1951   view()->OnSetZoomLevelForLoadingURL(params.url, kMaxZoomLevel);
1952   frame()->OnNavigate(params);
1953   ProcessPendingMessages();
1954   EXPECT_DOUBLE_EQ(kMaxZoomLevel, view()->GetWebView()->zoomLevel());
1955 }
1956
1957 TEST_F(RenderViewImplTest, SetEditableSelectionAndComposition) {
1958   // Load an HTML page consisting of an input field.
1959   LoadHTML("<html>"
1960            "<head>"
1961            "</head>"
1962            "<body>"
1963            "<input id=\"test1\" value=\"some test text hello\"></input>"
1964            "</body>"
1965            "</html>");
1966   ExecuteJavaScript("document.getElementById('test1').focus();");
1967   frame()->OnSetEditableSelectionOffsets(4, 8);
1968   const std::vector<blink::WebCompositionUnderline> empty_underline;
1969   frame()->OnSetCompositionFromExistingText(7, 10, empty_underline);
1970   blink::WebTextInputInfo info = view()->webview()->textInputInfo();
1971   EXPECT_EQ(4, info.selectionStart);
1972   EXPECT_EQ(8, info.selectionEnd);
1973   EXPECT_EQ(7, info.compositionStart);
1974   EXPECT_EQ(10, info.compositionEnd);
1975   frame()->OnUnselect();
1976   info = view()->webview()->textInputInfo();
1977   EXPECT_EQ(0, info.selectionStart);
1978   EXPECT_EQ(0, info.selectionEnd);
1979 }
1980
1981
1982 TEST_F(RenderViewImplTest, OnExtendSelectionAndDelete) {
1983   // Load an HTML page consisting of an input field.
1984   LoadHTML("<html>"
1985            "<head>"
1986            "</head>"
1987            "<body>"
1988            "<input id=\"test1\" value=\"abcdefghijklmnopqrstuvwxyz\"></input>"
1989            "</body>"
1990            "</html>");
1991   ExecuteJavaScript("document.getElementById('test1').focus();");
1992   frame()->OnSetEditableSelectionOffsets(10, 10);
1993   frame()->OnExtendSelectionAndDelete(3, 4);
1994   blink::WebTextInputInfo info = view()->webview()->textInputInfo();
1995   EXPECT_EQ("abcdefgopqrstuvwxyz", info.value);
1996   EXPECT_EQ(7, info.selectionStart);
1997   EXPECT_EQ(7, info.selectionEnd);
1998   frame()->OnSetEditableSelectionOffsets(4, 8);
1999   frame()->OnExtendSelectionAndDelete(2, 5);
2000   info = view()->webview()->textInputInfo();
2001   EXPECT_EQ("abuvwxyz", info.value);
2002   EXPECT_EQ(2, info.selectionStart);
2003   EXPECT_EQ(2, info.selectionEnd);
2004 }
2005
2006 // Test that the navigating specific frames works correctly.
2007 TEST_F(RenderViewImplTest, NavigateFrame) {
2008   // Load page A.
2009   LoadHTML("hello <iframe srcdoc='fail' name='frame'></iframe>");
2010
2011   // Navigate the frame only.
2012   FrameMsg_Navigate_Params nav_params;
2013   nav_params.url = GURL("data:text/html,world");
2014   nav_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
2015   nav_params.transition = PAGE_TRANSITION_TYPED;
2016   nav_params.current_history_list_length = 1;
2017   nav_params.current_history_list_offset = 0;
2018   nav_params.pending_history_list_offset = 1;
2019   nav_params.page_id = -1;
2020   nav_params.frame_to_navigate = "frame";
2021   frame()->OnNavigate(nav_params);
2022   FrameLoadWaiter(
2023       RenderFrame::FromWebFrame(frame()->GetWebFrame()->firstChild())).Wait();
2024
2025   // Copy the document content to std::wstring and compare with the
2026   // expected result.
2027   const int kMaxOutputCharacters = 256;
2028   std::string output = base::UTF16ToUTF8(
2029       GetMainFrame()->contentAsText(kMaxOutputCharacters));
2030   EXPECT_EQ(output, "hello \n\nworld");
2031 }
2032
2033 // This test ensures that a RenderFrame object is created for the top level
2034 // frame in the RenderView.
2035 TEST_F(RenderViewImplTest, BasicRenderFrame) {
2036   EXPECT_TRUE(view()->main_render_frame_.get());
2037 }
2038
2039 TEST_F(RenderViewImplTest, GetSSLStatusOfFrame) {
2040   LoadHTML("<!DOCTYPE html><html><body></body></html>");
2041
2042   WebLocalFrame* frame = GetMainFrame();
2043   SSLStatus ssl_status = view()->GetSSLStatusOfFrame(frame);
2044   EXPECT_FALSE(net::IsCertStatusError(ssl_status.cert_status));
2045
2046   const_cast<blink::WebURLResponse&>(frame->dataSource()->response()).
2047       setSecurityInfo(
2048           SerializeSecurityInfo(0, net::CERT_STATUS_ALL_ERRORS, 0, 0,
2049                                 SignedCertificateTimestampIDStatusList()));
2050   ssl_status = view()->GetSSLStatusOfFrame(frame);
2051   EXPECT_TRUE(net::IsCertStatusError(ssl_status.cert_status));
2052 }
2053
2054 TEST_F(RenderViewImplTest, MessageOrderInDidChangeSelection) {
2055   view()->OnSetInputMethodActive(true);
2056   view()->set_send_content_state_immediately(true);
2057   LoadHTML("<textarea id=\"test\"></textarea>");
2058
2059   view()->handling_input_event_ = true;
2060   ExecuteJavaScript("document.getElementById('test').focus();");
2061
2062   bool is_input_type_called = false;
2063   bool is_selection_called = false;
2064   size_t last_input_type = 0;
2065   size_t last_selection = 0;
2066
2067   for (size_t i = 0; i < render_thread_->sink().message_count(); ++i) {
2068     const uint32 type = render_thread_->sink().GetMessageAt(i)->type();
2069     if (type == ViewHostMsg_TextInputStateChanged::ID) {
2070       is_input_type_called = true;
2071       last_input_type = i;
2072     } else if (type == ViewHostMsg_SelectionChanged::ID) {
2073       is_selection_called = true;
2074       last_selection = i;
2075     }
2076   }
2077
2078   EXPECT_TRUE(is_input_type_called);
2079   EXPECT_TRUE(is_selection_called);
2080
2081   // InputTypeChange shold be called earlier than SelectionChanged.
2082   EXPECT_LT(last_input_type, last_selection);
2083 }
2084
2085 class SuppressErrorPageTest : public RenderViewTest {
2086  public:
2087   virtual ContentRendererClient* CreateContentRendererClient() OVERRIDE {
2088     return new TestContentRendererClient;
2089   }
2090
2091   RenderViewImpl* view() {
2092     return static_cast<RenderViewImpl*>(view_);
2093   }
2094
2095   RenderFrameImpl* frame() {
2096     return static_cast<RenderFrameImpl*>(view()->GetMainRenderFrame());
2097   }
2098
2099  private:
2100   class TestContentRendererClient : public ContentRendererClient {
2101    public:
2102     virtual bool ShouldSuppressErrorPage(RenderFrame* render_frame,
2103                                          const GURL& url) OVERRIDE {
2104       return url == GURL("http://example.com/suppress");
2105     }
2106
2107     virtual void GetNavigationErrorStrings(
2108         content::RenderView* render_view,
2109         blink::WebFrame* frame,
2110         const blink::WebURLRequest& failed_request,
2111         const blink::WebURLError& error,
2112         std::string* error_html,
2113         base::string16* error_description) OVERRIDE {
2114       if (error_html)
2115         *error_html = "A suffusion of yellow.";
2116     }
2117   };
2118 };
2119
2120 #if defined(OS_ANDROID)
2121 // Crashing on Android: http://crbug.com/311341
2122 #define MAYBE_Suppresses DISABLED_Suppresses
2123 #else
2124 #define MAYBE_Suppresses Suppresses
2125 #endif
2126
2127 TEST_F(SuppressErrorPageTest, MAYBE_Suppresses) {
2128   WebURLError error;
2129   error.domain = WebString::fromUTF8(net::kErrorDomain);
2130   error.reason = net::ERR_FILE_NOT_FOUND;
2131   error.unreachableURL = GURL("http://example.com/suppress");
2132   WebLocalFrame* web_frame = GetMainFrame();
2133
2134   // Start a load that will reach provisional state synchronously,
2135   // but won't complete synchronously.
2136   FrameMsg_Navigate_Params params;
2137   params.page_id = -1;
2138   params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
2139   params.url = GURL("data:text/html,test data");
2140   frame()->OnNavigate(params);
2141
2142   // An error occurred.
2143   view()->main_render_frame()->didFailProvisionalLoad(web_frame, error);
2144   const int kMaxOutputCharacters = 22;
2145   EXPECT_EQ("",
2146             base::UTF16ToASCII(web_frame->contentAsText(kMaxOutputCharacters)));
2147 }
2148
2149 #if defined(OS_ANDROID)
2150 // Crashing on Android: http://crbug.com/311341
2151 #define MAYBE_DoesNotSuppress DISABLED_DoesNotSuppress
2152 #else
2153 #define MAYBE_DoesNotSuppress DoesNotSuppress
2154 #endif
2155
2156 TEST_F(SuppressErrorPageTest, MAYBE_DoesNotSuppress) {
2157   WebURLError error;
2158   error.domain = WebString::fromUTF8(net::kErrorDomain);
2159   error.reason = net::ERR_FILE_NOT_FOUND;
2160   error.unreachableURL = GURL("http://example.com/dont-suppress");
2161   WebLocalFrame* web_frame = GetMainFrame();
2162
2163   // Start a load that will reach provisional state synchronously,
2164   // but won't complete synchronously.
2165   FrameMsg_Navigate_Params params;
2166   params.page_id = -1;
2167   params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
2168   params.url = GURL("data:text/html,test data");
2169   frame()->OnNavigate(params);
2170
2171   // An error occurred.
2172   view()->main_render_frame()->didFailProvisionalLoad(web_frame, error);
2173   // The error page itself is loaded asynchronously.
2174   FrameLoadWaiter(frame()).Wait();
2175   const int kMaxOutputCharacters = 22;
2176   EXPECT_EQ("A suffusion of yellow.",
2177             base::UTF16ToASCII(web_frame->contentAsText(kMaxOutputCharacters)));
2178 }
2179
2180 // Tests if IME API's candidatewindow* events sent from browser are handled
2181 // in renderer.
2182 TEST_F(RenderViewImplTest, SendCandidateWindowEvents) {
2183   // Sends an HTML with an <input> element and scripts to the renderer.
2184   // The script handles all 3 of candidatewindow* events for an
2185   // InputMethodContext object and once it received 'show', 'update', 'hide'
2186   // should appear in the result div.
2187   LoadHTML("<input id='test'>"
2188            "<div id='result'>Result: </div>"
2189            "<script>"
2190            "window.onload = function() {"
2191            "  var result = document.getElementById('result');"
2192            "  var test = document.getElementById('test');"
2193            "  test.focus();"
2194            "  var context = test.inputMethodContext;"
2195            "  if (context) {"
2196            "    context.oncandidatewindowshow = function() {"
2197            "        result.innerText += 'show'; };"
2198            "    context.oncandidatewindowupdate = function(){"
2199            "        result.innerText += 'update'; };"
2200            "    context.oncandidatewindowhide = function(){"
2201            "        result.innerText += 'hide'; };"
2202            "  }"
2203            "};"
2204            "</script>");
2205
2206   // Fire candidatewindow events.
2207   view()->OnCandidateWindowShown();
2208   view()->OnCandidateWindowUpdated();
2209   view()->OnCandidateWindowHidden();
2210
2211   // Retrieve the content and check if it is expected.
2212   const int kMaxOutputCharacters = 50;
2213   std::string output = base::UTF16ToUTF8(
2214       GetMainFrame()->contentAsText(kMaxOutputCharacters));
2215   EXPECT_EQ(output, "\nResult:showupdatehide");
2216 }
2217
2218 // Ensure the render view sends favicon url update events correctly.
2219 TEST_F(RenderViewImplTest, SendFaviconURLUpdateEvent) {
2220   // An event should be sent when a favicon url exists.
2221   LoadHTML("<html>"
2222            "<head>"
2223            "<link rel='icon' href='http://www.google.com/favicon.ico'>"
2224            "</head>"
2225            "</html>");
2226   EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching(
2227       ViewHostMsg_UpdateFaviconURL::ID));
2228   render_thread_->sink().ClearMessages();
2229
2230   // An event should not be sent if no favicon url exists. This is an assumption
2231   // made by some of Chrome's favicon handling.
2232   LoadHTML("<html>"
2233            "<head>"
2234            "</head>"
2235            "</html>");
2236   EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching(
2237       ViewHostMsg_UpdateFaviconURL::ID));
2238 }
2239
2240 TEST_F(RenderViewImplTest, FocusElementCallsFocusedNodeChanged) {
2241   LoadHTML("<input id='test1' value='hello1'></input>"
2242            "<input id='test2' value='hello2'></input>");
2243
2244   ExecuteJavaScript("document.getElementById('test1').focus();");
2245   const IPC::Message* msg1 = render_thread_->sink().GetFirstMessageMatching(
2246       ViewHostMsg_FocusedNodeChanged::ID);
2247   EXPECT_TRUE(msg1);
2248
2249   ViewHostMsg_FocusedNodeChanged::Param params;
2250   ViewHostMsg_FocusedNodeChanged::Read(msg1, &params);
2251   EXPECT_TRUE(params.a);
2252   render_thread_->sink().ClearMessages();
2253
2254   ExecuteJavaScript("document.getElementById('test2').focus();");
2255   const IPC::Message* msg2 = render_thread_->sink().GetFirstMessageMatching(
2256         ViewHostMsg_FocusedNodeChanged::ID);
2257   EXPECT_TRUE(msg2);
2258   ViewHostMsg_FocusedNodeChanged::Read(msg2, &params);
2259   EXPECT_TRUE(params.a);
2260   render_thread_->sink().ClearMessages();
2261
2262   view()->webview()->clearFocusedElement();
2263   const IPC::Message* msg3 = render_thread_->sink().GetFirstMessageMatching(
2264         ViewHostMsg_FocusedNodeChanged::ID);
2265   EXPECT_TRUE(msg3);
2266   ViewHostMsg_FocusedNodeChanged::Read(msg3, &params);
2267   EXPECT_FALSE(params.a);
2268   render_thread_->sink().ClearMessages();
2269 }
2270
2271 TEST_F(RenderViewImplTest, ServiceWorkerNetworkProviderSetup) {
2272   ServiceWorkerNetworkProvider* provider = NULL;
2273   RequestExtraData* extra_data = NULL;
2274
2275   // Make sure each new document has a new provider and
2276   // that the main request is tagged with the provider's id.
2277   LoadHTML("<b>A Document</b>");
2278   ASSERT_TRUE(GetMainFrame()->dataSource());
2279   provider = ServiceWorkerNetworkProvider::FromDocumentState(
2280       DocumentState::FromDataSource(GetMainFrame()->dataSource()));
2281   ASSERT_TRUE(provider);
2282   extra_data = static_cast<RequestExtraData*>(
2283       GetMainFrame()->dataSource()->request().extraData());
2284   ASSERT_TRUE(extra_data);
2285   EXPECT_EQ(extra_data->service_worker_provider_id(),
2286             provider->provider_id());
2287   int provider1_id = provider->provider_id();
2288
2289   LoadHTML("<b>New Document B Goes Here</b>");
2290   ASSERT_TRUE(GetMainFrame()->dataSource());
2291   provider = ServiceWorkerNetworkProvider::FromDocumentState(
2292       DocumentState::FromDataSource(GetMainFrame()->dataSource()));
2293   ASSERT_TRUE(provider);
2294   EXPECT_NE(provider1_id, provider->provider_id());
2295   extra_data = static_cast<RequestExtraData*>(
2296       GetMainFrame()->dataSource()->request().extraData());
2297   ASSERT_TRUE(extra_data);
2298   EXPECT_EQ(extra_data->service_worker_provider_id(),
2299             provider->provider_id());
2300
2301   // See that subresource requests are also tagged with the provider's id.
2302   EXPECT_EQ(frame(), RenderFrameImpl::FromWebFrame(GetMainFrame()));
2303   blink::WebURLRequest request(GURL("http://foo.com"));
2304   request.setTargetType(blink::WebURLRequest::TargetIsSubresource);
2305   blink::WebURLResponse redirect_response;
2306   frame()->willSendRequest(GetMainFrame(), 0, request, redirect_response);
2307   extra_data = static_cast<RequestExtraData*>(request.extraData());
2308   ASSERT_TRUE(extra_data);
2309   EXPECT_EQ(extra_data->service_worker_provider_id(),
2310             provider->provider_id());
2311 }
2312
2313 TEST_F(RenderViewImplTest, OnSetAccessibilityMode) {
2314   ASSERT_EQ(AccessibilityModeOff, view()->accessibility_mode());
2315   ASSERT_EQ((RendererAccessibility*) NULL, view()->renderer_accessibility());
2316
2317   view()->OnSetAccessibilityMode(AccessibilityModeTreeOnly);
2318   ASSERT_EQ(AccessibilityModeTreeOnly, view()->accessibility_mode());
2319   ASSERT_NE((RendererAccessibility*) NULL, view()->renderer_accessibility());
2320   ASSERT_EQ(RendererAccessibilityTypeComplete,
2321             view()->renderer_accessibility()->GetType());
2322
2323   view()->OnSetAccessibilityMode(AccessibilityModeOff);
2324   ASSERT_EQ(AccessibilityModeOff, view()->accessibility_mode());
2325   ASSERT_EQ((RendererAccessibility*) NULL, view()->renderer_accessibility());
2326
2327   view()->OnSetAccessibilityMode(AccessibilityModeComplete);
2328   ASSERT_EQ(AccessibilityModeComplete, view()->accessibility_mode());
2329   ASSERT_NE((RendererAccessibility*) NULL, view()->renderer_accessibility());
2330   ASSERT_EQ(RendererAccessibilityTypeComplete,
2331             view()->renderer_accessibility()->GetType());
2332
2333   view()->OnSetAccessibilityMode(AccessibilityModeEditableTextOnly);
2334   ASSERT_EQ(AccessibilityModeEditableTextOnly, view()->accessibility_mode());
2335   ASSERT_NE((RendererAccessibility*) NULL, view()->renderer_accessibility());
2336   ASSERT_EQ(RendererAccessibilityTypeFocusOnly,
2337             view()->renderer_accessibility()->GetType());
2338 }
2339
2340 }  // namespace content