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