Upstream version 11.39.250.0
[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()->UpdateTextInputType();
967     const IPC::Message* msg = render_thread_->sink().GetMessageAt(0);
968     EXPECT_TRUE(msg != NULL);
969     EXPECT_EQ(ViewHostMsg_TextInputTypeChanged::ID, msg->type());
970     ViewHostMsg_TextInputTypeChanged::Param params;
971     ViewHostMsg_TextInputTypeChanged::Read(msg, &params);
972     ui::TextInputType type = params.a;
973     ui::TextInputMode input_mode = params.b;
974     bool can_compose_inline = params.c;
975     EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, type);
976     EXPECT_EQ(true, can_compose_inline);
977
978     // Move the input focus to the second <input> element, where we should
979     // de-activate IMEs.
980     ExecuteJavaScript("document.getElementById('test2').focus();");
981     ProcessPendingMessages();
982     render_thread_->sink().ClearMessages();
983
984     // Update the IME status and verify if our IME backend sends an IPC message
985     // to de-activate IMEs.
986     view()->UpdateTextInputType();
987     msg = render_thread_->sink().GetMessageAt(0);
988     EXPECT_TRUE(msg != NULL);
989     EXPECT_EQ(ViewHostMsg_TextInputTypeChanged::ID, msg->type());
990     ViewHostMsg_TextInputTypeChanged::Read(msg, & params);
991     type = params.a;
992     input_mode = params.b;
993     EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, type);
994
995     for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kInputModeTestCases); i++) {
996       const InputModeTestCase* test_case = &kInputModeTestCases[i];
997       std::string javascript =
998           base::StringPrintf("document.getElementById('%s').focus();",
999                              test_case->input_id);
1000       // Move the input focus to the target <input> element, where we should
1001       // activate IMEs.
1002       ExecuteJavaScriptAndReturnIntValue(base::ASCIIToUTF16(javascript), NULL);
1003       ProcessPendingMessages();
1004       render_thread_->sink().ClearMessages();
1005
1006       // Update the IME status and verify if our IME backend sends an IPC
1007       // message to activate IMEs.
1008       view()->UpdateTextInputType();
1009       const IPC::Message* msg = render_thread_->sink().GetMessageAt(0);
1010       EXPECT_TRUE(msg != NULL);
1011       EXPECT_EQ(ViewHostMsg_TextInputTypeChanged::ID, msg->type());
1012       ViewHostMsg_TextInputTypeChanged::Read(msg, & params);
1013       type = params.a;
1014       input_mode = params.b;
1015       EXPECT_EQ(test_case->expected_mode, input_mode);
1016     }
1017   }
1018 }
1019
1020 // Test that our IME backend can compose CJK words.
1021 // Our IME front-end sends many platform-independent messages to the IME backend
1022 // while it composes CJK words. This test sends the minimal messages captured
1023 // on my local environment directly to the IME backend to verify if the backend
1024 // can compose CJK words without any problems.
1025 // This test uses an array of command sets because an IME composotion does not
1026 // only depends on IME events, but also depends on window events, e.g. moving
1027 // the window focus while composing a CJK text. To handle such complicated
1028 // cases, this test should not only call IME-related functions in the
1029 // RenderWidget class, but also call some RenderWidget members, e.g.
1030 // ExecuteJavaScript(), RenderWidget::OnSetFocus(), etc.
1031 TEST_F(RenderViewImplTest, ImeComposition) {
1032   enum ImeCommand {
1033     IME_INITIALIZE,
1034     IME_SETINPUTMODE,
1035     IME_SETFOCUS,
1036     IME_SETCOMPOSITION,
1037     IME_CONFIRMCOMPOSITION,
1038     IME_CANCELCOMPOSITION
1039   };
1040   struct ImeMessage {
1041     ImeCommand command;
1042     bool enable;
1043     int selection_start;
1044     int selection_end;
1045     const wchar_t* ime_string;
1046     const wchar_t* result;
1047   };
1048   static const ImeMessage kImeMessages[] = {
1049     // Scenario 1: input a Chinese word with Microsoft IME (on Vista).
1050     {IME_INITIALIZE, true, 0, 0, NULL, NULL},
1051     {IME_SETINPUTMODE, true, 0, 0, NULL, NULL},
1052     {IME_SETFOCUS, true, 0, 0, NULL, NULL},
1053     {IME_SETCOMPOSITION, false, 1, 1, L"n", L"n"},
1054     {IME_SETCOMPOSITION, false, 2, 2, L"ni", L"ni"},
1055     {IME_SETCOMPOSITION, false, 3, 3, L"nih", L"nih"},
1056     {IME_SETCOMPOSITION, false, 4, 4, L"niha", L"niha"},
1057     {IME_SETCOMPOSITION, false, 5, 5, L"nihao", L"nihao"},
1058     {IME_CONFIRMCOMPOSITION, false, -1, -1, L"\x4F60\x597D", L"\x4F60\x597D"},
1059     // Scenario 2: input a Japanese word with Microsoft IME (on Vista).
1060     {IME_INITIALIZE, true, 0, 0, NULL, NULL},
1061     {IME_SETINPUTMODE, true, 0, 0, NULL, NULL},
1062     {IME_SETFOCUS, true, 0, 0, NULL, NULL},
1063     {IME_SETCOMPOSITION, false, 0, 1, L"\xFF4B", L"\xFF4B"},
1064     {IME_SETCOMPOSITION, false, 0, 1, L"\x304B", L"\x304B"},
1065     {IME_SETCOMPOSITION, false, 0, 2, L"\x304B\xFF4E", L"\x304B\xFF4E"},
1066     {IME_SETCOMPOSITION, false, 0, 3, L"\x304B\x3093\xFF4A",
1067      L"\x304B\x3093\xFF4A"},
1068     {IME_SETCOMPOSITION, false, 0, 3, L"\x304B\x3093\x3058",
1069      L"\x304B\x3093\x3058"},
1070     {IME_SETCOMPOSITION, false, 0, 2, L"\x611F\x3058", L"\x611F\x3058"},
1071     {IME_SETCOMPOSITION, false, 0, 2, L"\x6F22\x5B57", L"\x6F22\x5B57"},
1072     {IME_CONFIRMCOMPOSITION, false, -1, -1, L"", L"\x6F22\x5B57"},
1073     {IME_CANCELCOMPOSITION, false, -1, -1, L"", L"\x6F22\x5B57"},
1074     // Scenario 3: input a Korean word with Microsot IME (on Vista).
1075     {IME_INITIALIZE, true, 0, 0, NULL, NULL},
1076     {IME_SETINPUTMODE, true, 0, 0, NULL, NULL},
1077     {IME_SETFOCUS, true, 0, 0, NULL, NULL},
1078     {IME_SETCOMPOSITION, false, 0, 1, L"\x3147", L"\x3147"},
1079     {IME_SETCOMPOSITION, false, 0, 1, L"\xC544", L"\xC544"},
1080     {IME_SETCOMPOSITION, false, 0, 1, L"\xC548", L"\xC548"},
1081     {IME_CONFIRMCOMPOSITION, false, -1, -1, L"", L"\xC548"},
1082     {IME_SETCOMPOSITION, false, 0, 1, L"\x3134", L"\xC548\x3134"},
1083     {IME_SETCOMPOSITION, false, 0, 1, L"\xB140", L"\xC548\xB140"},
1084     {IME_SETCOMPOSITION, false, 0, 1, L"\xB155", L"\xC548\xB155"},
1085     {IME_CANCELCOMPOSITION, false, -1, -1, L"", L"\xC548"},
1086     {IME_SETCOMPOSITION, false, 0, 1, L"\xB155", L"\xC548\xB155"},
1087     {IME_CONFIRMCOMPOSITION, false, -1, -1, L"", L"\xC548\xB155"},
1088   };
1089
1090   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kImeMessages); i++) {
1091     const ImeMessage* ime_message = &kImeMessages[i];
1092     switch (ime_message->command) {
1093       case IME_INITIALIZE:
1094         // Load an HTML page consisting of a content-editable <div> element,
1095         // and move the input focus to the <div> element, where we can use
1096         // IMEs.
1097         view()->OnSetInputMethodActive(ime_message->enable);
1098         view()->set_send_content_state_immediately(true);
1099         LoadHTML("<html>"
1100                 "<head>"
1101                 "</head>"
1102                 "<body>"
1103                 "<div id=\"test1\" contenteditable=\"true\"></div>"
1104                 "</body>"
1105                 "</html>");
1106         ExecuteJavaScript("document.getElementById('test1').focus();");
1107         break;
1108
1109       case IME_SETINPUTMODE:
1110         // Activate (or deactivate) our IME back-end.
1111         view()->OnSetInputMethodActive(ime_message->enable);
1112         break;
1113
1114       case IME_SETFOCUS:
1115         // Update the window focus.
1116         view()->OnSetFocus(ime_message->enable);
1117         break;
1118
1119       case IME_SETCOMPOSITION:
1120         view()->OnImeSetComposition(
1121             base::WideToUTF16(ime_message->ime_string),
1122             std::vector<blink::WebCompositionUnderline>(),
1123             ime_message->selection_start,
1124             ime_message->selection_end);
1125         break;
1126
1127       case IME_CONFIRMCOMPOSITION:
1128         view()->OnImeConfirmComposition(
1129             base::WideToUTF16(ime_message->ime_string),
1130             gfx::Range::InvalidRange(),
1131             false);
1132         break;
1133
1134       case IME_CANCELCOMPOSITION:
1135         view()->OnImeSetComposition(
1136             base::string16(),
1137             std::vector<blink::WebCompositionUnderline>(),
1138             0, 0);
1139         break;
1140     }
1141
1142     // Update the status of our IME back-end.
1143     // TODO(hbono): we should verify messages to be sent from the back-end.
1144     view()->UpdateTextInputType();
1145     ProcessPendingMessages();
1146     render_thread_->sink().ClearMessages();
1147
1148     if (ime_message->result) {
1149       // Retrieve the content of this page and compare it with the expected
1150       // result.
1151       const int kMaxOutputCharacters = 128;
1152       base::string16 output =
1153           GetMainFrame()->contentAsText(kMaxOutputCharacters);
1154       EXPECT_EQ(base::WideToUTF16(ime_message->result), output);
1155     }
1156   }
1157 }
1158
1159 // Test that the RenderView::OnSetTextDirection() function can change the text
1160 // direction of the selected input element.
1161 TEST_F(RenderViewImplTest, OnSetTextDirection) {
1162   // Load an HTML page consisting of a <textarea> element and a <div> element.
1163   // This test changes the text direction of the <textarea> element, and
1164   // writes the values of its 'dir' attribute and its 'direction' property to
1165   // verify that the text direction is changed.
1166   view()->set_send_content_state_immediately(true);
1167   LoadHTML("<html>"
1168            "<head>"
1169            "</head>"
1170            "<body>"
1171            "<textarea id=\"test\"></textarea>"
1172            "<div id=\"result\" contenteditable=\"true\"></div>"
1173            "</body>"
1174            "</html>");
1175   render_thread_->sink().ClearMessages();
1176
1177   static const struct {
1178     WebTextDirection direction;
1179     const wchar_t* expected_result;
1180   } kTextDirection[] = {
1181     { blink::WebTextDirectionRightToLeft, L"\x000A" L"rtl,rtl" },
1182     { blink::WebTextDirectionLeftToRight, L"\x000A" L"ltr,ltr" },
1183   };
1184   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTextDirection); ++i) {
1185     // Set the text direction of the <textarea> element.
1186     ExecuteJavaScript("document.getElementById('test').focus();");
1187     view()->OnSetTextDirection(kTextDirection[i].direction);
1188
1189     // Write the values of its DOM 'dir' attribute and its CSS 'direction'
1190     // property to the <div> element.
1191     ExecuteJavaScript("var result = document.getElementById('result');"
1192                       "var node = document.getElementById('test');"
1193                       "var style = getComputedStyle(node, null);"
1194                       "result.innerText ="
1195                       "    node.getAttribute('dir') + ',' +"
1196                       "    style.getPropertyValue('direction');");
1197
1198     // Copy the document content to std::wstring and compare with the
1199     // expected result.
1200     const int kMaxOutputCharacters = 16;
1201     base::string16 output = GetMainFrame()->contentAsText(kMaxOutputCharacters);
1202     EXPECT_EQ(base::WideToUTF16(kTextDirection[i].expected_result), output);
1203   }
1204 }
1205
1206 // see http://crbug.com/238750
1207 #if defined(OS_WIN)
1208 #define MAYBE_OnHandleKeyboardEvent DISABLED_OnHandleKeyboardEvent
1209 #else
1210 #define MAYBE_OnHandleKeyboardEvent OnHandleKeyboardEvent
1211 #endif
1212
1213 // Test that we can receive correct DOM events when we send input events
1214 // through the RenderWidget::OnHandleInputEvent() function.
1215 TEST_F(RenderViewImplTest, MAYBE_OnHandleKeyboardEvent) {
1216 #if !defined(OS_MACOSX)
1217   // Load an HTML page consisting of one <input> element and three
1218   // contentediable <div> elements.
1219   // The <input> element is used for sending keyboard events, and the <div>
1220   // elements are used for writing DOM events in the following format:
1221   //   "<keyCode>,<shiftKey>,<controlKey>,<altKey>".
1222   // TODO(hbono): <http://crbug.com/2215> Our WebKit port set |ev.metaKey| to
1223   // true when pressing an alt key, i.e. the |ev.metaKey| value is not
1224   // trustworthy. We will check the |ev.metaKey| value when this issue is fixed.
1225   view()->set_send_content_state_immediately(true);
1226   LoadHTML("<html>"
1227            "<head>"
1228            "<title></title>"
1229            "<script type='text/javascript' language='javascript'>"
1230            "function OnKeyEvent(ev) {"
1231            "  var result = document.getElementById(ev.type);"
1232            "  result.innerText ="
1233            "      (ev.which || ev.keyCode) + ',' +"
1234            "      ev.shiftKey + ',' +"
1235            "      ev.ctrlKey + ',' +"
1236            "      ev.altKey;"
1237            "  return true;"
1238            "}"
1239            "</script>"
1240            "</head>"
1241            "<body>"
1242            "<input id='test' type='text'"
1243            "    onkeydown='return OnKeyEvent(event);'"
1244            "    onkeypress='return OnKeyEvent(event);'"
1245            "    onkeyup='return OnKeyEvent(event);'>"
1246            "</input>"
1247            "<div id='keydown' contenteditable='true'>"
1248            "</div>"
1249            "<div id='keypress' contenteditable='true'>"
1250            "</div>"
1251            "<div id='keyup' contenteditable='true'>"
1252            "</div>"
1253            "</body>"
1254            "</html>");
1255   ExecuteJavaScript("document.getElementById('test').focus();");
1256   render_thread_->sink().ClearMessages();
1257
1258   static const MockKeyboard::Layout kLayouts[] = {
1259 #if defined(OS_WIN)
1260     // Since we ignore the mock keyboard layout on Linux and instead just use
1261     // the screen's keyboard layout, these trivially pass. They are commented
1262     // out to avoid the illusion that they work.
1263     MockKeyboard::LAYOUT_ARABIC,
1264     MockKeyboard::LAYOUT_CANADIAN_FRENCH,
1265     MockKeyboard::LAYOUT_FRENCH,
1266     MockKeyboard::LAYOUT_HEBREW,
1267     MockKeyboard::LAYOUT_RUSSIAN,
1268 #endif
1269     MockKeyboard::LAYOUT_UNITED_STATES,
1270   };
1271
1272   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kLayouts); ++i) {
1273     // For each key code, we send three keyboard events.
1274     //  * we press only the key;
1275     //  * we press the key and a left-shift key, and;
1276     //  * we press the key and a right-alt (AltGr) key.
1277     // For each modifiers, we need a string used for formatting its expected
1278     // result. (See the above comment for its format.)
1279     static const struct {
1280       MockKeyboard::Modifiers modifiers;
1281       const char* expected_result;
1282     } kModifierData[] = {
1283       {MockKeyboard::NONE,       "false,false,false"},
1284       {MockKeyboard::LEFT_SHIFT, "true,false,false"},
1285 #if defined(OS_WIN)
1286       {MockKeyboard::RIGHT_ALT,  "false,false,true"},
1287 #endif
1288     };
1289
1290     MockKeyboard::Layout layout = kLayouts[i];
1291     for (size_t j = 0; j < ARRAYSIZE_UNSAFE(kModifierData); ++j) {
1292       // Virtual key codes used for this test.
1293       static const int kKeyCodes[] = {
1294         '0', '1', '2', '3', '4', '5', '6', '7',
1295         '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
1296         'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
1297         'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
1298         'W', 'X', 'Y', 'Z',
1299         ui::VKEY_OEM_1,
1300         ui::VKEY_OEM_PLUS,
1301         ui::VKEY_OEM_COMMA,
1302         ui::VKEY_OEM_MINUS,
1303         ui::VKEY_OEM_PERIOD,
1304         ui::VKEY_OEM_2,
1305         ui::VKEY_OEM_3,
1306         ui::VKEY_OEM_4,
1307         ui::VKEY_OEM_5,
1308         ui::VKEY_OEM_6,
1309         ui::VKEY_OEM_7,
1310 #if defined(OS_WIN)
1311         // Not sure how to handle this key on Linux.
1312         ui::VKEY_OEM_8,
1313 #endif
1314       };
1315
1316       MockKeyboard::Modifiers modifiers = kModifierData[j].modifiers;
1317       for (size_t k = 0; k < ARRAYSIZE_UNSAFE(kKeyCodes); ++k) {
1318         // Send a keyboard event to the RenderView object.
1319         // We should test a keyboard event only when the given keyboard-layout
1320         // driver is installed in a PC and the driver can assign a Unicode
1321         // charcter for the given tuple (key-code and modifiers).
1322         int key_code = kKeyCodes[k];
1323         base::string16 char_code;
1324         if (SendKeyEvent(layout, key_code, modifiers, &char_code) < 0)
1325           continue;
1326
1327         // Create an expected result from the virtual-key code, the character
1328         // code, and the modifier-key status.
1329         // We format a string that emulates a DOM-event string produced hy
1330         // our JavaScript function. (See the above comment for the format.)
1331         static char expected_result[1024];
1332         expected_result[0] = 0;
1333         base::snprintf(&expected_result[0],
1334                        sizeof(expected_result),
1335                        "\n"       // texts in the <input> element
1336                        "%d,%s\n"  // texts in the first <div> element
1337                        "%d,%s\n"  // texts in the second <div> element
1338                        "%d,%s",   // texts in the third <div> element
1339                        key_code, kModifierData[j].expected_result,
1340                        static_cast<int>(char_code[0]),
1341                        kModifierData[j].expected_result,
1342                        key_code, kModifierData[j].expected_result);
1343
1344         // Retrieve the text in the test page and compare it with the expected
1345         // text created from a virtual-key code, a character code, and the
1346         // modifier-key status.
1347         const int kMaxOutputCharacters = 1024;
1348         std::string output = base::UTF16ToUTF8(
1349             GetMainFrame()->contentAsText(kMaxOutputCharacters));
1350         EXPECT_EQ(expected_result, output);
1351       }
1352     }
1353   }
1354 #else
1355   NOTIMPLEMENTED();
1356 #endif
1357 }
1358
1359 // Test that our EditorClientImpl class can insert characters when we send
1360 // keyboard events through the RenderWidget::OnHandleInputEvent() function.
1361 // This test is for preventing regressions caused only when we use non-US
1362 // keyboards, such as Issue 10846.
1363 // see http://crbug.com/244562
1364 #if defined(OS_WIN)
1365 #define MAYBE_InsertCharacters DISABLED_InsertCharacters
1366 #else
1367 #define MAYBE_InsertCharacters InsertCharacters
1368 #endif
1369 TEST_F(RenderViewImplTest, MAYBE_InsertCharacters) {
1370 #if !defined(OS_MACOSX)
1371   static const struct {
1372     MockKeyboard::Layout layout;
1373     const wchar_t* expected_result;
1374   } kLayouts[] = {
1375 #if 0
1376     // Disabled these keyboard layouts because buildbots do not have their
1377     // keyboard-layout drivers installed.
1378     {MockKeyboard::LAYOUT_ARABIC,
1379      L"\x0030\x0031\x0032\x0033\x0034\x0035\x0036\x0037"
1380      L"\x0038\x0039\x0634\x0624\x064a\x062b\x0628\x0644"
1381      L"\x0627\x0647\x062a\x0646\x0645\x0629\x0649\x062e"
1382      L"\x062d\x0636\x0642\x0633\x0641\x0639\x0631\x0635"
1383      L"\x0621\x063a\x0626\x0643\x003d\x0648\x002d\x0632"
1384      L"\x0638\x0630\x062c\x005c\x062f\x0637\x0028\x0021"
1385      L"\x0040\x0023\x0024\x0025\x005e\x0026\x002a\x0029"
1386      L"\x0650\x007d\x005d\x064f\x005b\x0623\x00f7\x0640"
1387      L"\x060c\x002f\x2019\x0622\x00d7\x061b\x064e\x064c"
1388      L"\x064d\x2018\x007b\x064b\x0652\x0625\x007e\x003a"
1389      L"\x002b\x002c\x005f\x002e\x061f\x0651\x003c\x007c"
1390      L"\x003e\x0022\x0030\x0031\x0032\x0033\x0034\x0035"
1391      L"\x0036\x0037\x0038\x0039\x0634\x0624\x064a\x062b"
1392      L"\x0628\x0644\x0627\x0647\x062a\x0646\x0645\x0629"
1393      L"\x0649\x062e\x062d\x0636\x0642\x0633\x0641\x0639"
1394      L"\x0631\x0635\x0621\x063a\x0626\x0643\x003d\x0648"
1395      L"\x002d\x0632\x0638\x0630\x062c\x005c\x062f\x0637"
1396     },
1397     {MockKeyboard::LAYOUT_HEBREW,
1398      L"\x0030\x0031\x0032\x0033\x0034\x0035\x0036\x0037"
1399      L"\x0038\x0039\x05e9\x05e0\x05d1\x05d2\x05e7\x05db"
1400      L"\x05e2\x05d9\x05df\x05d7\x05dc\x05da\x05e6\x05de"
1401      L"\x05dd\x05e4\x002f\x05e8\x05d3\x05d0\x05d5\x05d4"
1402      L"\x0027\x05e1\x05d8\x05d6\x05e3\x003d\x05ea\x002d"
1403      L"\x05e5\x002e\x003b\x005d\x005c\x005b\x002c\x0028"
1404      L"\x0021\x0040\x0023\x0024\x0025\x005e\x0026\x002a"
1405      L"\x0029\x0041\x0042\x0043\x0044\x0045\x0046\x0047"
1406      L"\x0048\x0049\x004a\x004b\x004c\x004d\x004e\x004f"
1407      L"\x0050\x0051\x0052\x0053\x0054\x0055\x0056\x0057"
1408      L"\x0058\x0059\x005a\x003a\x002b\x003e\x005f\x003c"
1409      L"\x003f\x007e\x007d\x007c\x007b\x0022\x0030\x0031"
1410      L"\x0032\x0033\x0034\x0035\x0036\x0037\x0038\x0039"
1411      L"\x05e9\x05e0\x05d1\x05d2\x05e7\x05db\x05e2\x05d9"
1412      L"\x05df\x05d7\x05dc\x05da\x05e6\x05de\x05dd\x05e4"
1413      L"\x002f\x05e8\x05d3\x05d0\x05d5\x05d4\x0027\x05e1"
1414      L"\x05d8\x05d6\x05e3\x003d\x05ea\x002d\x05e5\x002e"
1415      L"\x003b\x005d\x005c\x005b\x002c"
1416     },
1417 #endif
1418 #if defined(OS_WIN)
1419     // On Linux, the only way to test alternate keyboard layouts is to change
1420     // the keyboard layout of the whole screen. I'm worried about the side
1421     // effects this may have on the buildbots.
1422     {MockKeyboard::LAYOUT_CANADIAN_FRENCH,
1423      L"\x0030\x0031\x0032\x0033\x0034\x0035\x0036\x0037"
1424      L"\x0038\x0039\x0061\x0062\x0063\x0064\x0065\x0066"
1425      L"\x0067\x0068\x0069\x006a\x006b\x006c\x006d\x006e"
1426      L"\x006f\x0070\x0071\x0072\x0073\x0074\x0075\x0076"
1427      L"\x0077\x0078\x0079\x007a\x003b\x003d\x002c\x002d"
1428      L"\x002e\x00e9\x003c\x0029\x0021\x0022\x002f\x0024"
1429      L"\x0025\x003f\x0026\x002a\x0028\x0041\x0042\x0043"
1430      L"\x0044\x0045\x0046\x0047\x0048\x0049\x004a\x004b"
1431      L"\x004c\x004d\x004e\x004f\x0050\x0051\x0052\x0053"
1432      L"\x0054\x0055\x0056\x0057\x0058\x0059\x005a\x003a"
1433      L"\x002b\x0027\x005f\x002e\x00c9\x003e\x0030\x0031"
1434      L"\x0032\x0033\x0034\x0035\x0036\x0037\x0038\x0039"
1435      L"\x0061\x0062\x0063\x0064\x0065\x0066\x0067\x0068"
1436      L"\x0069\x006a\x006b\x006c\x006d\x006e\x006f\x0070"
1437      L"\x0071\x0072\x0073\x0074\x0075\x0076\x0077\x0078"
1438      L"\x0079\x007a\x003b\x003d\x002c\x002d\x002e\x00e9"
1439      L"\x003c"
1440     },
1441     {MockKeyboard::LAYOUT_FRENCH,
1442      L"\x00e0\x0026\x00e9\x0022\x0027\x0028\x002d\x00e8"
1443      L"\x005f\x00e7\x0061\x0062\x0063\x0064\x0065\x0066"
1444      L"\x0067\x0068\x0069\x006a\x006b\x006c\x006d\x006e"
1445      L"\x006f\x0070\x0071\x0072\x0073\x0074\x0075\x0076"
1446      L"\x0077\x0078\x0079\x007a\x0024\x003d\x002c\x003b"
1447      L"\x003a\x00f9\x0029\x002a\x0021\x0030\x0031\x0032"
1448      L"\x0033\x0034\x0035\x0036\x0037\x0038\x0039\x0041"
1449      L"\x0042\x0043\x0044\x0045\x0046\x0047\x0048\x0049"
1450      L"\x004a\x004b\x004c\x004d\x004e\x004f\x0050\x0051"
1451      L"\x0052\x0053\x0054\x0055\x0056\x0057\x0058\x0059"
1452      L"\x005a\x00a3\x002b\x003f\x002e\x002f\x0025\x00b0"
1453      L"\x00b5\x00e0\x0026\x00e9\x0022\x0027\x0028\x002d"
1454      L"\x00e8\x005f\x00e7\x0061\x0062\x0063\x0064\x0065"
1455      L"\x0066\x0067\x0068\x0069\x006a\x006b\x006c\x006d"
1456      L"\x006e\x006f\x0070\x0071\x0072\x0073\x0074\x0075"
1457      L"\x0076\x0077\x0078\x0079\x007a\x0024\x003d\x002c"
1458      L"\x003b\x003a\x00f9\x0029\x002a\x0021"
1459     },
1460     {MockKeyboard::LAYOUT_RUSSIAN,
1461      L"\x0030\x0031\x0032\x0033\x0034\x0035\x0036\x0037"
1462      L"\x0038\x0039\x0444\x0438\x0441\x0432\x0443\x0430"
1463      L"\x043f\x0440\x0448\x043e\x043b\x0434\x044c\x0442"
1464      L"\x0449\x0437\x0439\x043a\x044b\x0435\x0433\x043c"
1465      L"\x0446\x0447\x043d\x044f\x0436\x003d\x0431\x002d"
1466      L"\x044e\x002e\x0451\x0445\x005c\x044a\x044d\x0029"
1467      L"\x0021\x0022\x2116\x003b\x0025\x003a\x003f\x002a"
1468      L"\x0028\x0424\x0418\x0421\x0412\x0423\x0410\x041f"
1469      L"\x0420\x0428\x041e\x041b\x0414\x042c\x0422\x0429"
1470      L"\x0417\x0419\x041a\x042b\x0415\x0413\x041c\x0426"
1471      L"\x0427\x041d\x042f\x0416\x002b\x0411\x005f\x042e"
1472      L"\x002c\x0401\x0425\x002f\x042a\x042d\x0030\x0031"
1473      L"\x0032\x0033\x0034\x0035\x0036\x0037\x0038\x0039"
1474      L"\x0444\x0438\x0441\x0432\x0443\x0430\x043f\x0440"
1475      L"\x0448\x043e\x043b\x0434\x044c\x0442\x0449\x0437"
1476      L"\x0439\x043a\x044b\x0435\x0433\x043c\x0446\x0447"
1477      L"\x043d\x044f\x0436\x003d\x0431\x002d\x044e\x002e"
1478      L"\x0451\x0445\x005c\x044a\x044d"
1479     },
1480 #endif  // defined(OS_WIN)
1481     {MockKeyboard::LAYOUT_UNITED_STATES,
1482      L"\x0030\x0031\x0032\x0033\x0034\x0035\x0036\x0037"
1483      L"\x0038\x0039\x0061\x0062\x0063\x0064\x0065\x0066"
1484      L"\x0067\x0068\x0069\x006a\x006b\x006c\x006d\x006e"
1485      L"\x006f\x0070\x0071\x0072\x0073\x0074\x0075\x0076"
1486      L"\x0077\x0078\x0079\x007a\x003b\x003d\x002c\x002d"
1487      L"\x002e\x002f\x0060\x005b\x005c\x005d\x0027\x0029"
1488      L"\x0021\x0040\x0023\x0024\x0025\x005e\x0026\x002a"
1489      L"\x0028\x0041\x0042\x0043\x0044\x0045\x0046\x0047"
1490      L"\x0048\x0049\x004a\x004b\x004c\x004d\x004e\x004f"
1491      L"\x0050\x0051\x0052\x0053\x0054\x0055\x0056\x0057"
1492      L"\x0058\x0059\x005a\x003a\x002b\x003c\x005f\x003e"
1493      L"\x003f\x007e\x007b\x007c\x007d\x0022"
1494 #if defined(OS_WIN)
1495      // This is ifdefed out for Linux to correspond to the fact that we don't
1496      // test alt+keystroke for now.
1497      L"\x0030\x0031\x0032\x0033\x0034\x0035\x0036\x0037"
1498      L"\x0038\x0039\x0061\x0062\x0063\x0064\x0065\x0066"
1499      L"\x0067\x0068\x0069\x006a\x006b\x006c\x006d\x006e"
1500      L"\x006f\x0070\x0071\x0072\x0073\x0074\x0075\x0076"
1501      L"\x0077\x0078\x0079\x007a\x003b\x003d\x002c\x002d"
1502      L"\x002e\x002f\x0060\x005b\x005c\x005d\x0027"
1503 #endif
1504     },
1505   };
1506
1507   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kLayouts); ++i) {
1508     // Load an HTML page consisting of one <div> element.
1509     // This <div> element is used by the EditorClientImpl class to insert
1510     // characters received through the RenderWidget::OnHandleInputEvent()
1511     // function.
1512     view()->set_send_content_state_immediately(true);
1513     LoadHTML("<html>"
1514              "<head>"
1515              "<title></title>"
1516              "</head>"
1517              "<body>"
1518              "<div id='test' contenteditable='true'>"
1519              "</div>"
1520              "</body>"
1521              "</html>");
1522     ExecuteJavaScript("document.getElementById('test').focus();");
1523     render_thread_->sink().ClearMessages();
1524
1525     // For each key code, we send three keyboard events.
1526     //  * Pressing only the key;
1527     //  * Pressing the key and a left-shift key, and;
1528     //  * Pressing the key and a right-alt (AltGr) key.
1529     static const MockKeyboard::Modifiers kModifiers[] = {
1530       MockKeyboard::NONE,
1531       MockKeyboard::LEFT_SHIFT,
1532 #if defined(OS_WIN)
1533       MockKeyboard::RIGHT_ALT,
1534 #endif
1535     };
1536
1537     MockKeyboard::Layout layout = kLayouts[i].layout;
1538     for (size_t j = 0; j < ARRAYSIZE_UNSAFE(kModifiers); ++j) {
1539       // Virtual key codes used for this test.
1540       static const int kKeyCodes[] = {
1541         '0', '1', '2', '3', '4', '5', '6', '7',
1542         '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
1543         'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
1544         'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
1545         'W', 'X', 'Y', 'Z',
1546         ui::VKEY_OEM_1,
1547         ui::VKEY_OEM_PLUS,
1548         ui::VKEY_OEM_COMMA,
1549         ui::VKEY_OEM_MINUS,
1550         ui::VKEY_OEM_PERIOD,
1551         ui::VKEY_OEM_2,
1552         ui::VKEY_OEM_3,
1553         ui::VKEY_OEM_4,
1554         ui::VKEY_OEM_5,
1555         ui::VKEY_OEM_6,
1556         ui::VKEY_OEM_7,
1557 #if defined(OS_WIN)
1558         // Unclear how to handle this on Linux.
1559         ui::VKEY_OEM_8,
1560 #endif
1561       };
1562
1563       MockKeyboard::Modifiers modifiers = kModifiers[j];
1564       for (size_t k = 0; k < ARRAYSIZE_UNSAFE(kKeyCodes); ++k) {
1565         // Send a keyboard event to the RenderView object.
1566         // We should test a keyboard event only when the given keyboard-layout
1567         // driver is installed in a PC and the driver can assign a Unicode
1568         // charcter for the given tuple (layout, key-code, and modifiers).
1569         int key_code = kKeyCodes[k];
1570         base::string16 char_code;
1571         if (SendKeyEvent(layout, key_code, modifiers, &char_code) < 0)
1572           continue;
1573       }
1574     }
1575
1576     // Retrieve the text in the test page and compare it with the expected
1577     // text created from a virtual-key code, a character code, and the
1578     // modifier-key status.
1579     const int kMaxOutputCharacters = 4096;
1580     base::string16 output = GetMainFrame()->contentAsText(kMaxOutputCharacters);
1581     EXPECT_EQ(base::WideToUTF16(kLayouts[i].expected_result), output);
1582   }
1583 #else
1584   NOTIMPLEMENTED();
1585 #endif
1586 }
1587
1588 // Crashy, http://crbug.com/53247.
1589 TEST_F(RenderViewImplTest, DISABLED_DidFailProvisionalLoadWithErrorForError) {
1590   GetMainFrame()->enableViewSourceMode(true);
1591   WebURLError error;
1592   error.domain = WebString::fromUTF8(net::kErrorDomain);
1593   error.reason = net::ERR_FILE_NOT_FOUND;
1594   error.unreachableURL = GURL("http://foo");
1595   WebLocalFrame* web_frame = GetMainFrame();
1596
1597   // Start a load that will reach provisional state synchronously,
1598   // but won't complete synchronously.
1599   FrameMsg_Navigate_Params params;
1600   params.page_id = -1;
1601   params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
1602   params.url = GURL("data:text/html,test data");
1603   params.browser_navigation_start = base::TimeTicks::FromInternalValue(1);
1604   frame()->OnNavigate(params);
1605
1606   // An error occurred.
1607   view()->GetMainRenderFrame()->didFailProvisionalLoad(web_frame, error);
1608   // Frame should exit view-source mode.
1609   EXPECT_FALSE(web_frame->isViewSourceModeEnabled());
1610 }
1611
1612 TEST_F(RenderViewImplTest, DidFailProvisionalLoadWithErrorForCancellation) {
1613   GetMainFrame()->enableViewSourceMode(true);
1614   WebURLError error;
1615   error.domain = WebString::fromUTF8(net::kErrorDomain);
1616   error.reason = net::ERR_ABORTED;
1617   error.unreachableURL = GURL("http://foo");
1618   WebLocalFrame* web_frame = GetMainFrame();
1619
1620   // Start a load that will reach provisional state synchronously,
1621   // but won't complete synchronously.
1622   FrameMsg_Navigate_Params params;
1623   params.page_id = -1;
1624   params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
1625   params.url = GURL("data:text/html,test data");
1626   params.browser_navigation_start = base::TimeTicks::FromInternalValue(1);
1627   frame()->OnNavigate(params);
1628
1629   // A cancellation occurred.
1630   view()->GetMainRenderFrame()->didFailProvisionalLoad(web_frame, error);
1631   // Frame should stay in view-source mode.
1632   EXPECT_TRUE(web_frame->isViewSourceModeEnabled());
1633 }
1634
1635 // Regression test for http://crbug.com/41562
1636 TEST_F(RenderViewImplTest, UpdateTargetURLWithInvalidURL) {
1637   const GURL invalid_gurl("http://");
1638   view()->setMouseOverURL(blink::WebURL(invalid_gurl));
1639   EXPECT_EQ(invalid_gurl, view()->target_url_);
1640 }
1641
1642 TEST_F(RenderViewImplTest, SetHistoryLengthAndPrune) {
1643   int expected_page_id = -1;
1644
1645   // No history to merge and no committed pages.
1646   view()->OnSetHistoryLengthAndPrune(0, -1);
1647   EXPECT_EQ(0, view()->history_list_length_);
1648   EXPECT_EQ(-1, view()->history_list_offset_);
1649
1650   // History to merge and no committed pages.
1651   view()->OnSetHistoryLengthAndPrune(2, -1);
1652   EXPECT_EQ(2, view()->history_list_length_);
1653   EXPECT_EQ(1, view()->history_list_offset_);
1654   EXPECT_EQ(-1, view()->history_page_ids_[0]);
1655   EXPECT_EQ(-1, view()->history_page_ids_[1]);
1656   ClearHistory();
1657
1658   blink::WebHistoryItem item;
1659   item.initialize();
1660
1661   // No history to merge and a committed page to be kept.
1662   frame()->didCommitProvisionalLoad(GetMainFrame(),
1663                                     item,
1664                                     blink::WebStandardCommit);
1665   expected_page_id = view()->page_id_;
1666   view()->OnSetHistoryLengthAndPrune(0, expected_page_id);
1667   EXPECT_EQ(1, view()->history_list_length_);
1668   EXPECT_EQ(0, view()->history_list_offset_);
1669   EXPECT_EQ(expected_page_id, view()->history_page_ids_[0]);
1670   ClearHistory();
1671
1672   // No history to merge and a committed page to be pruned.
1673   frame()->didCommitProvisionalLoad(GetMainFrame(),
1674                                     item,
1675                                     blink::WebStandardCommit);
1676   expected_page_id = view()->page_id_;
1677   view()->OnSetHistoryLengthAndPrune(0, expected_page_id + 1);
1678   EXPECT_EQ(0, view()->history_list_length_);
1679   EXPECT_EQ(-1, view()->history_list_offset_);
1680   ClearHistory();
1681
1682   // No history to merge and a committed page that the browser was unaware of.
1683   frame()->didCommitProvisionalLoad(GetMainFrame(),
1684                                     item,
1685                                     blink::WebStandardCommit);
1686   expected_page_id = view()->page_id_;
1687   view()->OnSetHistoryLengthAndPrune(0, -1);
1688   EXPECT_EQ(1, view()->history_list_length_);
1689   EXPECT_EQ(0, view()->history_list_offset_);
1690   EXPECT_EQ(expected_page_id, view()->history_page_ids_[0]);
1691   ClearHistory();
1692
1693   // History to merge and a committed page to be kept.
1694   frame()->didCommitProvisionalLoad(GetMainFrame(),
1695                                     item,
1696                                     blink::WebStandardCommit);
1697   expected_page_id = view()->page_id_;
1698   view()->OnSetHistoryLengthAndPrune(2, expected_page_id);
1699   EXPECT_EQ(3, view()->history_list_length_);
1700   EXPECT_EQ(2, view()->history_list_offset_);
1701   EXPECT_EQ(-1, view()->history_page_ids_[0]);
1702   EXPECT_EQ(-1, view()->history_page_ids_[1]);
1703   EXPECT_EQ(expected_page_id, view()->history_page_ids_[2]);
1704   ClearHistory();
1705
1706   // History to merge and a committed page to be pruned.
1707   frame()->didCommitProvisionalLoad(GetMainFrame(),
1708                                     item,
1709                                     blink::WebStandardCommit);
1710   expected_page_id = view()->page_id_;
1711   view()->OnSetHistoryLengthAndPrune(2, expected_page_id + 1);
1712   EXPECT_EQ(2, view()->history_list_length_);
1713   EXPECT_EQ(1, view()->history_list_offset_);
1714   EXPECT_EQ(-1, view()->history_page_ids_[0]);
1715   EXPECT_EQ(-1, view()->history_page_ids_[1]);
1716   ClearHistory();
1717
1718   // History to merge and a committed page that the browser was unaware of.
1719   frame()->didCommitProvisionalLoad(GetMainFrame(),
1720                                     item,
1721                                     blink::WebStandardCommit);
1722   expected_page_id = view()->page_id_;
1723   view()->OnSetHistoryLengthAndPrune(2, -1);
1724   EXPECT_EQ(3, view()->history_list_length_);
1725   EXPECT_EQ(2, view()->history_list_offset_);
1726   EXPECT_EQ(-1, view()->history_page_ids_[0]);
1727   EXPECT_EQ(-1, view()->history_page_ids_[1]);
1728   EXPECT_EQ(expected_page_id, view()->history_page_ids_[2]);
1729   ClearHistory();
1730
1731   int expected_page_id_2 = -1;
1732
1733   // No history to merge and two committed pages, both to be kept.
1734   frame()->didCommitProvisionalLoad(GetMainFrame(),
1735                                     item,
1736                                     blink::WebStandardCommit);
1737   expected_page_id = view()->page_id_;
1738   frame()->didCommitProvisionalLoad(GetMainFrame(),
1739                                     item,
1740                                     blink::WebStandardCommit);
1741   expected_page_id_2 = view()->page_id_;
1742   EXPECT_GT(expected_page_id_2, expected_page_id);
1743   view()->OnSetHistoryLengthAndPrune(0, expected_page_id);
1744   EXPECT_EQ(2, view()->history_list_length_);
1745   EXPECT_EQ(1, view()->history_list_offset_);
1746   EXPECT_EQ(expected_page_id, view()->history_page_ids_[0]);
1747   EXPECT_EQ(expected_page_id_2, view()->history_page_ids_[1]);
1748   ClearHistory();
1749
1750   // No history to merge and two committed pages, and only the second is kept.
1751   frame()->didCommitProvisionalLoad(GetMainFrame(),
1752                                     item,
1753                                     blink::WebStandardCommit);
1754   expected_page_id = view()->page_id_;
1755   frame()->didCommitProvisionalLoad(GetMainFrame(),
1756                                     item,
1757                                     blink::WebStandardCommit);
1758   expected_page_id_2 = view()->page_id_;
1759   EXPECT_GT(expected_page_id_2, expected_page_id);
1760   view()->OnSetHistoryLengthAndPrune(0, expected_page_id_2);
1761   EXPECT_EQ(1, view()->history_list_length_);
1762   EXPECT_EQ(0, view()->history_list_offset_);
1763   EXPECT_EQ(expected_page_id_2, view()->history_page_ids_[0]);
1764   ClearHistory();
1765
1766   // No history to merge and two committed pages, both of which the browser was
1767   // unaware of.
1768   frame()->didCommitProvisionalLoad(GetMainFrame(),
1769                                     item,
1770                                     blink::WebStandardCommit);
1771   expected_page_id = view()->page_id_;
1772   frame()->didCommitProvisionalLoad(GetMainFrame(),
1773                                     item,
1774                                     blink::WebStandardCommit);
1775   expected_page_id_2 = view()->page_id_;
1776   EXPECT_GT(expected_page_id_2, expected_page_id);
1777   view()->OnSetHistoryLengthAndPrune(0, -1);
1778   EXPECT_EQ(2, view()->history_list_length_);
1779   EXPECT_EQ(1, view()->history_list_offset_);
1780   EXPECT_EQ(expected_page_id, view()->history_page_ids_[0]);
1781   EXPECT_EQ(expected_page_id_2, view()->history_page_ids_[1]);
1782   ClearHistory();
1783
1784   // History to merge and two committed pages, both to be kept.
1785   frame()->didCommitProvisionalLoad(GetMainFrame(),
1786                                     item,
1787                                     blink::WebStandardCommit);
1788   expected_page_id = view()->page_id_;
1789   frame()->didCommitProvisionalLoad(GetMainFrame(),
1790                                     item,
1791                                     blink::WebStandardCommit);
1792   expected_page_id_2 = view()->page_id_;
1793   EXPECT_GT(expected_page_id_2, expected_page_id);
1794   view()->OnSetHistoryLengthAndPrune(2, expected_page_id);
1795   EXPECT_EQ(4, view()->history_list_length_);
1796   EXPECT_EQ(3, view()->history_list_offset_);
1797   EXPECT_EQ(-1, view()->history_page_ids_[0]);
1798   EXPECT_EQ(-1, view()->history_page_ids_[1]);
1799   EXPECT_EQ(expected_page_id, view()->history_page_ids_[2]);
1800   EXPECT_EQ(expected_page_id_2, view()->history_page_ids_[3]);
1801   ClearHistory();
1802
1803   // History to merge and two committed pages, and only the second is kept.
1804   frame()->didCommitProvisionalLoad(GetMainFrame(),
1805                                     item,
1806                                     blink::WebStandardCommit);
1807   expected_page_id = view()->page_id_;
1808   frame()->didCommitProvisionalLoad(GetMainFrame(),
1809                                     item,
1810                                     blink::WebStandardCommit);
1811   expected_page_id_2 = view()->page_id_;
1812   EXPECT_GT(expected_page_id_2, expected_page_id);
1813   view()->OnSetHistoryLengthAndPrune(2, expected_page_id_2);
1814   EXPECT_EQ(3, view()->history_list_length_);
1815   EXPECT_EQ(2, view()->history_list_offset_);
1816   EXPECT_EQ(-1, view()->history_page_ids_[0]);
1817   EXPECT_EQ(-1, view()->history_page_ids_[1]);
1818   EXPECT_EQ(expected_page_id_2, view()->history_page_ids_[2]);
1819   ClearHistory();
1820
1821   // History to merge and two committed pages, both of which the browser was
1822   // unaware of.
1823   frame()->didCommitProvisionalLoad(GetMainFrame(),
1824                                     item,
1825                                     blink::WebStandardCommit);
1826   expected_page_id = view()->page_id_;
1827   frame()->didCommitProvisionalLoad(GetMainFrame(),
1828                                     item,
1829                                     blink::WebStandardCommit);
1830   expected_page_id_2 = view()->page_id_;
1831   EXPECT_GT(expected_page_id_2, expected_page_id);
1832   view()->OnSetHistoryLengthAndPrune(2, -1);
1833   EXPECT_EQ(4, view()->history_list_length_);
1834   EXPECT_EQ(3, view()->history_list_offset_);
1835   EXPECT_EQ(-1, view()->history_page_ids_[0]);
1836   EXPECT_EQ(-1, view()->history_page_ids_[1]);
1837   EXPECT_EQ(expected_page_id, view()->history_page_ids_[2]);
1838   EXPECT_EQ(expected_page_id_2, view()->history_page_ids_[3]);
1839 }
1840
1841 TEST_F(RenderViewImplTest, ContextMenu) {
1842   LoadHTML("<div>Page A</div>");
1843
1844   // Create a right click in the center of the iframe. (I'm hoping this will
1845   // make this a bit more robust in case of some other formatting or other bug.)
1846   WebMouseEvent mouse_event;
1847   mouse_event.type = WebInputEvent::MouseDown;
1848   mouse_event.button = WebMouseEvent::ButtonRight;
1849   mouse_event.x = 250;
1850   mouse_event.y = 250;
1851   mouse_event.globalX = 250;
1852   mouse_event.globalY = 250;
1853
1854   SendWebMouseEvent(mouse_event);
1855
1856   // Now simulate the corresponding up event which should display the menu
1857   mouse_event.type = WebInputEvent::MouseUp;
1858   SendWebMouseEvent(mouse_event);
1859
1860   EXPECT_TRUE(render_thread_->sink().GetUniqueMessageMatching(
1861       FrameHostMsg_ContextMenu::ID));
1862 }
1863
1864 TEST_F(RenderViewImplTest, TestBackForward) {
1865   LoadHTML("<div id=pagename>Page A</div>");
1866   PageState page_a_state =
1867       HistoryEntryToPageState(view()->history_controller()->GetCurrentEntry());
1868   int was_page_a = -1;
1869   base::string16 check_page_a =
1870       base::ASCIIToUTF16(
1871           "Number(document.getElementById('pagename').innerHTML == 'Page A')");
1872   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_a, &was_page_a));
1873   EXPECT_EQ(1, was_page_a);
1874
1875   LoadHTML("<div id=pagename>Page B</div>");
1876   int was_page_b = -1;
1877   base::string16 check_page_b =
1878       base::ASCIIToUTF16(
1879           "Number(document.getElementById('pagename').innerHTML == 'Page B')");
1880   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_b, &was_page_b));
1881   EXPECT_EQ(1, was_page_b);
1882
1883   PageState back_state =
1884       HistoryEntryToPageState(view()->history_controller()->GetCurrentEntry());
1885
1886   LoadHTML("<div id=pagename>Page C</div>");
1887   int was_page_c = -1;
1888   base::string16 check_page_c =
1889       base::ASCIIToUTF16(
1890           "Number(document.getElementById('pagename').innerHTML == 'Page C')");
1891   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_c, &was_page_c));
1892   EXPECT_EQ(1, was_page_b);
1893
1894   PageState forward_state =
1895       HistoryEntryToPageState(view()->history_controller()->GetCurrentEntry());
1896   GoBack(back_state);
1897   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_b, &was_page_b));
1898   EXPECT_EQ(1, was_page_b);
1899
1900   PageState back_state2 =
1901       HistoryEntryToPageState(view()->history_controller()->GetCurrentEntry());
1902
1903   GoForward(forward_state);
1904   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_c, &was_page_c));
1905   EXPECT_EQ(1, was_page_c);
1906
1907   GoBack(back_state2);
1908   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_b, &was_page_b));
1909   EXPECT_EQ(1, was_page_b);
1910
1911   forward_state =
1912       HistoryEntryToPageState(view()->history_controller()->GetCurrentEntry());
1913   GoBack(page_a_state);
1914   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_a, &was_page_a));
1915   EXPECT_EQ(1, was_page_a);
1916
1917   GoForward(forward_state);
1918   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_b, &was_page_b));
1919   EXPECT_EQ(1, was_page_b);
1920 }
1921
1922 #if defined(OS_MACOSX) || defined(USE_AURA)
1923 TEST_F(RenderViewImplTest, GetCompositionCharacterBoundsTest) {
1924
1925 #if defined(OS_WIN)
1926   // http://crbug.com/304193
1927   if (base::win::GetVersion() < base::win::VERSION_VISTA)
1928     return;
1929 #endif
1930
1931   LoadHTML("<textarea id=\"test\"></textarea>");
1932   ExecuteJavaScript("document.getElementById('test').focus();");
1933
1934   const base::string16 empty_string;
1935   const std::vector<blink::WebCompositionUnderline> empty_underline;
1936   std::vector<gfx::Rect> bounds;
1937   view()->OnSetFocus(true);
1938   view()->OnSetInputMethodActive(true);
1939
1940   // ASCII composition
1941   const base::string16 ascii_composition = base::UTF8ToUTF16("aiueo");
1942   view()->OnImeSetComposition(ascii_composition, empty_underline, 0, 0);
1943   view()->GetCompositionCharacterBounds(&bounds);
1944   ASSERT_EQ(ascii_composition.size(), bounds.size());
1945   for (size_t i = 0; i < bounds.size(); ++i)
1946     EXPECT_LT(0, bounds[i].width());
1947   view()->OnImeConfirmComposition(
1948       empty_string, gfx::Range::InvalidRange(), false);
1949
1950   // Non surrogate pair unicode character.
1951   const base::string16 unicode_composition = base::UTF8ToUTF16(
1952       "\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86\xE3\x81\x88\xE3\x81\x8A");
1953   view()->OnImeSetComposition(unicode_composition, empty_underline, 0, 0);
1954   view()->GetCompositionCharacterBounds(&bounds);
1955   ASSERT_EQ(unicode_composition.size(), bounds.size());
1956   for (size_t i = 0; i < bounds.size(); ++i)
1957     EXPECT_LT(0, bounds[i].width());
1958   view()->OnImeConfirmComposition(
1959       empty_string, gfx::Range::InvalidRange(), false);
1960
1961   // Surrogate pair character.
1962   const base::string16 surrogate_pair_char =
1963       base::UTF8ToUTF16("\xF0\xA0\xAE\x9F");
1964   view()->OnImeSetComposition(surrogate_pair_char,
1965                               empty_underline,
1966                               0,
1967                               0);
1968   view()->GetCompositionCharacterBounds(&bounds);
1969   ASSERT_EQ(surrogate_pair_char.size(), bounds.size());
1970   EXPECT_LT(0, bounds[0].width());
1971   EXPECT_EQ(0, bounds[1].width());
1972   view()->OnImeConfirmComposition(
1973       empty_string, gfx::Range::InvalidRange(), false);
1974
1975   // Mixed string.
1976   const base::string16 surrogate_pair_mixed_composition =
1977       surrogate_pair_char + base::UTF8ToUTF16("\xE3\x81\x82") +
1978       surrogate_pair_char + base::UTF8ToUTF16("b") + surrogate_pair_char;
1979   const size_t utf16_length = 8UL;
1980   const bool is_surrogate_pair_empty_rect[8] = {
1981     false, true, false, false, true, false, false, true };
1982   view()->OnImeSetComposition(surrogate_pair_mixed_composition,
1983                               empty_underline,
1984                               0,
1985                               0);
1986   view()->GetCompositionCharacterBounds(&bounds);
1987   ASSERT_EQ(utf16_length, bounds.size());
1988   for (size_t i = 0; i < utf16_length; ++i) {
1989     if (is_surrogate_pair_empty_rect[i]) {
1990       EXPECT_EQ(0, bounds[i].width());
1991     } else {
1992       EXPECT_LT(0, bounds[i].width());
1993     }
1994   }
1995   view()->OnImeConfirmComposition(
1996       empty_string, gfx::Range::InvalidRange(), false);
1997 }
1998 #endif
1999
2000 TEST_F(RenderViewImplTest, ZoomLimit) {
2001   const double kMinZoomLevel = ZoomFactorToZoomLevel(kMinimumZoomFactor);
2002   const double kMaxZoomLevel = ZoomFactorToZoomLevel(kMaximumZoomFactor);
2003
2004   FrameMsg_Navigate_Params params;
2005   params.page_id = -1;
2006   params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
2007   params.browser_navigation_start = base::TimeTicks::FromInternalValue(1);
2008
2009   // Verifies navigation to a URL with preset zoom level indeed sets the level.
2010   // Regression test for http://crbug.com/139559, where the level was not
2011   // properly set when it is out of the default zoom limits of WebView.
2012   params.url = GURL("data:text/html,min_zoomlimit_test");
2013   view()->OnSetZoomLevelForLoadingURL(params.url, kMinZoomLevel);
2014   frame()->OnNavigate(params);
2015   ProcessPendingMessages();
2016   EXPECT_DOUBLE_EQ(kMinZoomLevel, view()->GetWebView()->zoomLevel());
2017
2018   // It should work even when the zoom limit is temporarily changed in the page.
2019   view()->GetWebView()->zoomLimitsChanged(ZoomFactorToZoomLevel(1.0),
2020                                           ZoomFactorToZoomLevel(1.0));
2021   params.url = GURL("data:text/html,max_zoomlimit_test");
2022   view()->OnSetZoomLevelForLoadingURL(params.url, kMaxZoomLevel);
2023   frame()->OnNavigate(params);
2024   ProcessPendingMessages();
2025   EXPECT_DOUBLE_EQ(kMaxZoomLevel, view()->GetWebView()->zoomLevel());
2026 }
2027
2028 TEST_F(RenderViewImplTest, SetEditableSelectionAndComposition) {
2029   // Load an HTML page consisting of an input field.
2030   LoadHTML("<html>"
2031            "<head>"
2032            "</head>"
2033            "<body>"
2034            "<input id=\"test1\" value=\"some test text hello\"></input>"
2035            "</body>"
2036            "</html>");
2037   ExecuteJavaScript("document.getElementById('test1').focus();");
2038   frame()->OnSetEditableSelectionOffsets(4, 8);
2039   const std::vector<blink::WebCompositionUnderline> empty_underline;
2040   frame()->OnSetCompositionFromExistingText(7, 10, empty_underline);
2041   blink::WebTextInputInfo info = view()->webview()->textInputInfo();
2042   EXPECT_EQ(4, info.selectionStart);
2043   EXPECT_EQ(8, info.selectionEnd);
2044   EXPECT_EQ(7, info.compositionStart);
2045   EXPECT_EQ(10, info.compositionEnd);
2046   frame()->OnUnselect();
2047   info = view()->webview()->textInputInfo();
2048   EXPECT_EQ(0, info.selectionStart);
2049   EXPECT_EQ(0, info.selectionEnd);
2050 }
2051
2052
2053 TEST_F(RenderViewImplTest, OnExtendSelectionAndDelete) {
2054   // Load an HTML page consisting of an input field.
2055   LoadHTML("<html>"
2056            "<head>"
2057            "</head>"
2058            "<body>"
2059            "<input id=\"test1\" value=\"abcdefghijklmnopqrstuvwxyz\"></input>"
2060            "</body>"
2061            "</html>");
2062   ExecuteJavaScript("document.getElementById('test1').focus();");
2063   frame()->OnSetEditableSelectionOffsets(10, 10);
2064   frame()->OnExtendSelectionAndDelete(3, 4);
2065   blink::WebTextInputInfo info = view()->webview()->textInputInfo();
2066   EXPECT_EQ("abcdefgopqrstuvwxyz", info.value);
2067   EXPECT_EQ(7, info.selectionStart);
2068   EXPECT_EQ(7, info.selectionEnd);
2069   frame()->OnSetEditableSelectionOffsets(4, 8);
2070   frame()->OnExtendSelectionAndDelete(2, 5);
2071   info = view()->webview()->textInputInfo();
2072   EXPECT_EQ("abuvwxyz", info.value);
2073   EXPECT_EQ(2, info.selectionStart);
2074   EXPECT_EQ(2, info.selectionEnd);
2075 }
2076
2077 // Test that the navigating specific frames works correctly.
2078 TEST_F(RenderViewImplTest, NavigateFrame) {
2079   // Load page A.
2080   LoadHTML("hello <iframe srcdoc='fail' name='frame'></iframe>");
2081
2082   // Navigate the frame only.
2083   FrameMsg_Navigate_Params nav_params;
2084   nav_params.url = GURL("data:text/html,world");
2085   nav_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
2086   nav_params.transition = ui::PAGE_TRANSITION_TYPED;
2087   nav_params.current_history_list_length = 1;
2088   nav_params.current_history_list_offset = 0;
2089   nav_params.pending_history_list_offset = 1;
2090   nav_params.page_id = -1;
2091   nav_params.frame_to_navigate = "frame";
2092   nav_params.browser_navigation_start = base::TimeTicks::FromInternalValue(1);
2093   frame()->OnNavigate(nav_params);
2094   FrameLoadWaiter(
2095       RenderFrame::FromWebFrame(frame()->GetWebFrame()->firstChild())).Wait();
2096
2097   // Copy the document content to std::wstring and compare with the
2098   // expected result.
2099   const int kMaxOutputCharacters = 256;
2100   std::string output = base::UTF16ToUTF8(
2101       GetMainFrame()->contentAsText(kMaxOutputCharacters));
2102   EXPECT_EQ(output, "hello \n\nworld");
2103 }
2104
2105 // This test ensures that a RenderFrame object is created for the top level
2106 // frame in the RenderView.
2107 TEST_F(RenderViewImplTest, BasicRenderFrame) {
2108   EXPECT_TRUE(view()->main_render_frame_.get());
2109 }
2110
2111 TEST_F(RenderViewImplTest, GetSSLStatusOfFrame) {
2112   LoadHTML("<!DOCTYPE html><html><body></body></html>");
2113
2114   WebLocalFrame* frame = GetMainFrame();
2115   SSLStatus ssl_status = view()->GetSSLStatusOfFrame(frame);
2116   EXPECT_FALSE(net::IsCertStatusError(ssl_status.cert_status));
2117
2118   const_cast<blink::WebURLResponse&>(frame->dataSource()->response()).
2119       setSecurityInfo(
2120           SerializeSecurityInfo(0, net::CERT_STATUS_ALL_ERRORS, 0, 0,
2121                                 SignedCertificateTimestampIDStatusList()));
2122   ssl_status = view()->GetSSLStatusOfFrame(frame);
2123   EXPECT_TRUE(net::IsCertStatusError(ssl_status.cert_status));
2124 }
2125
2126 TEST_F(RenderViewImplTest, MessageOrderInDidChangeSelection) {
2127   view()->OnSetInputMethodActive(true);
2128   view()->set_send_content_state_immediately(true);
2129   LoadHTML("<textarea id=\"test\"></textarea>");
2130
2131   view()->handling_input_event_ = true;
2132   ExecuteJavaScript("document.getElementById('test').focus();");
2133
2134   bool is_input_type_called = false;
2135   bool is_selection_called = false;
2136   size_t last_input_type = 0;
2137   size_t last_selection = 0;
2138
2139   for (size_t i = 0; i < render_thread_->sink().message_count(); ++i) {
2140     const uint32 type = render_thread_->sink().GetMessageAt(i)->type();
2141     if (type == ViewHostMsg_TextInputTypeChanged::ID) {
2142       is_input_type_called = true;
2143       last_input_type = i;
2144     } else if (type == ViewHostMsg_SelectionChanged::ID) {
2145       is_selection_called = true;
2146       last_selection = i;
2147     }
2148   }
2149
2150   EXPECT_TRUE(is_input_type_called);
2151   EXPECT_TRUE(is_selection_called);
2152
2153   // InputTypeChange shold be called earlier than SelectionChanged.
2154   EXPECT_LT(last_input_type, last_selection);
2155 }
2156
2157 class SuppressErrorPageTest : public RenderViewTest {
2158  public:
2159   virtual ContentRendererClient* CreateContentRendererClient() OVERRIDE {
2160     return new TestContentRendererClient;
2161   }
2162
2163   RenderViewImpl* view() {
2164     return static_cast<RenderViewImpl*>(view_);
2165   }
2166
2167   RenderFrameImpl* frame() {
2168     return static_cast<RenderFrameImpl*>(view()->GetMainRenderFrame());
2169   }
2170
2171  private:
2172   class TestContentRendererClient : public ContentRendererClient {
2173    public:
2174     virtual bool ShouldSuppressErrorPage(RenderFrame* render_frame,
2175                                          const GURL& url) OVERRIDE {
2176       return url == GURL("http://example.com/suppress");
2177     }
2178
2179     virtual void GetNavigationErrorStrings(
2180         content::RenderView* render_view,
2181         blink::WebFrame* frame,
2182         const blink::WebURLRequest& failed_request,
2183         const blink::WebURLError& error,
2184         std::string* error_html,
2185         base::string16* error_description) OVERRIDE {
2186       if (error_html)
2187         *error_html = "A suffusion of yellow.";
2188     }
2189   };
2190 };
2191
2192 #if defined(OS_ANDROID)
2193 // Crashing on Android: http://crbug.com/311341
2194 #define MAYBE_Suppresses DISABLED_Suppresses
2195 #else
2196 #define MAYBE_Suppresses Suppresses
2197 #endif
2198
2199 TEST_F(SuppressErrorPageTest, MAYBE_Suppresses) {
2200   WebURLError error;
2201   error.domain = WebString::fromUTF8(net::kErrorDomain);
2202   error.reason = net::ERR_FILE_NOT_FOUND;
2203   error.unreachableURL = GURL("http://example.com/suppress");
2204   WebLocalFrame* web_frame = GetMainFrame();
2205
2206   // Start a load that will reach provisional state synchronously,
2207   // but won't complete synchronously.
2208   FrameMsg_Navigate_Params params;
2209   params.page_id = -1;
2210   params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
2211   params.url = GURL("data:text/html,test data");
2212   params.browser_navigation_start = base::TimeTicks::FromInternalValue(1);
2213   frame()->OnNavigate(params);
2214
2215   // An error occurred.
2216   view()->GetMainRenderFrame()->didFailProvisionalLoad(web_frame, error);
2217   const int kMaxOutputCharacters = 22;
2218   EXPECT_EQ("",
2219             base::UTF16ToASCII(web_frame->contentAsText(kMaxOutputCharacters)));
2220 }
2221
2222 #if defined(OS_ANDROID)
2223 // Crashing on Android: http://crbug.com/311341
2224 #define MAYBE_DoesNotSuppress DISABLED_DoesNotSuppress
2225 #else
2226 #define MAYBE_DoesNotSuppress DoesNotSuppress
2227 #endif
2228
2229 TEST_F(SuppressErrorPageTest, MAYBE_DoesNotSuppress) {
2230   WebURLError error;
2231   error.domain = WebString::fromUTF8(net::kErrorDomain);
2232   error.reason = net::ERR_FILE_NOT_FOUND;
2233   error.unreachableURL = GURL("http://example.com/dont-suppress");
2234   WebLocalFrame* web_frame = GetMainFrame();
2235
2236   // Start a load that will reach provisional state synchronously,
2237   // but won't complete synchronously.
2238   FrameMsg_Navigate_Params params;
2239   params.page_id = -1;
2240   params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
2241   params.url = GURL("data:text/html,test data");
2242   params.browser_navigation_start = base::TimeTicks::FromInternalValue(1);
2243   frame()->OnNavigate(params);
2244
2245   // An error occurred.
2246   view()->GetMainRenderFrame()->didFailProvisionalLoad(web_frame, error);
2247   // The error page itself is loaded asynchronously.
2248   FrameLoadWaiter(frame()).Wait();
2249   const int kMaxOutputCharacters = 22;
2250   EXPECT_EQ("A suffusion of yellow.",
2251             base::UTF16ToASCII(web_frame->contentAsText(kMaxOutputCharacters)));
2252 }
2253
2254 // Tests if IME API's candidatewindow* events sent from browser are handled
2255 // in renderer.
2256 TEST_F(RenderViewImplTest, SendCandidateWindowEvents) {
2257   // Sends an HTML with an <input> element and scripts to the renderer.
2258   // The script handles all 3 of candidatewindow* events for an
2259   // InputMethodContext object and once it received 'show', 'update', 'hide'
2260   // should appear in the result div.
2261   LoadHTML("<input id='test'>"
2262            "<div id='result'>Result: </div>"
2263            "<script>"
2264            "window.onload = function() {"
2265            "  var result = document.getElementById('result');"
2266            "  var test = document.getElementById('test');"
2267            "  test.focus();"
2268            "  var context = test.inputMethodContext;"
2269            "  if (context) {"
2270            "    context.oncandidatewindowshow = function() {"
2271            "        result.innerText += 'show'; };"
2272            "    context.oncandidatewindowupdate = function(){"
2273            "        result.innerText += 'update'; };"
2274            "    context.oncandidatewindowhide = function(){"
2275            "        result.innerText += 'hide'; };"
2276            "  }"
2277            "};"
2278            "</script>");
2279
2280   // Fire candidatewindow events.
2281   view()->OnCandidateWindowShown();
2282   view()->OnCandidateWindowUpdated();
2283   view()->OnCandidateWindowHidden();
2284
2285   // Retrieve the content and check if it is expected.
2286   const int kMaxOutputCharacters = 50;
2287   std::string output = base::UTF16ToUTF8(
2288       GetMainFrame()->contentAsText(kMaxOutputCharacters));
2289   EXPECT_EQ(output, "\nResult:showupdatehide");
2290 }
2291
2292 // Ensure the render view sends favicon url update events correctly.
2293 TEST_F(RenderViewImplTest, SendFaviconURLUpdateEvent) {
2294   // An event should be sent when a favicon url exists.
2295   LoadHTML("<html>"
2296            "<head>"
2297            "<link rel='icon' href='http://www.google.com/favicon.ico'>"
2298            "</head>"
2299            "</html>");
2300   EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching(
2301       ViewHostMsg_UpdateFaviconURL::ID));
2302   render_thread_->sink().ClearMessages();
2303
2304   // An event should not be sent if no favicon url exists. This is an assumption
2305   // made by some of Chrome's favicon handling.
2306   LoadHTML("<html>"
2307            "<head>"
2308            "</head>"
2309            "</html>");
2310   EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching(
2311       ViewHostMsg_UpdateFaviconURL::ID));
2312 }
2313
2314 TEST_F(RenderViewImplTest, FocusElementCallsFocusedNodeChanged) {
2315   LoadHTML("<input id='test1' value='hello1'></input>"
2316            "<input id='test2' value='hello2'></input>");
2317
2318   ExecuteJavaScript("document.getElementById('test1').focus();");
2319   const IPC::Message* msg1 = render_thread_->sink().GetFirstMessageMatching(
2320       ViewHostMsg_FocusedNodeChanged::ID);
2321   EXPECT_TRUE(msg1);
2322
2323   ViewHostMsg_FocusedNodeChanged::Param params;
2324   ViewHostMsg_FocusedNodeChanged::Read(msg1, &params);
2325   EXPECT_TRUE(params.a);
2326   render_thread_->sink().ClearMessages();
2327
2328   ExecuteJavaScript("document.getElementById('test2').focus();");
2329   const IPC::Message* msg2 = render_thread_->sink().GetFirstMessageMatching(
2330         ViewHostMsg_FocusedNodeChanged::ID);
2331   EXPECT_TRUE(msg2);
2332   ViewHostMsg_FocusedNodeChanged::Read(msg2, &params);
2333   EXPECT_TRUE(params.a);
2334   render_thread_->sink().ClearMessages();
2335
2336   view()->webview()->clearFocusedElement();
2337   const IPC::Message* msg3 = render_thread_->sink().GetFirstMessageMatching(
2338         ViewHostMsg_FocusedNodeChanged::ID);
2339   EXPECT_TRUE(msg3);
2340   ViewHostMsg_FocusedNodeChanged::Read(msg3, &params);
2341   EXPECT_FALSE(params.a);
2342   render_thread_->sink().ClearMessages();
2343 }
2344
2345 TEST_F(RenderViewImplTest, ServiceWorkerNetworkProviderSetup) {
2346   ServiceWorkerNetworkProvider* provider = NULL;
2347   RequestExtraData* extra_data = NULL;
2348
2349   // Make sure each new document has a new provider and
2350   // that the main request is tagged with the provider's id.
2351   LoadHTML("<b>A Document</b>");
2352   ASSERT_TRUE(GetMainFrame()->dataSource());
2353   provider = ServiceWorkerNetworkProvider::FromDocumentState(
2354       DocumentState::FromDataSource(GetMainFrame()->dataSource()));
2355   ASSERT_TRUE(provider);
2356   extra_data = static_cast<RequestExtraData*>(
2357       GetMainFrame()->dataSource()->request().extraData());
2358   ASSERT_TRUE(extra_data);
2359   EXPECT_EQ(extra_data->service_worker_provider_id(),
2360             provider->provider_id());
2361   int provider1_id = provider->provider_id();
2362
2363   LoadHTML("<b>New Document B Goes Here</b>");
2364   ASSERT_TRUE(GetMainFrame()->dataSource());
2365   provider = ServiceWorkerNetworkProvider::FromDocumentState(
2366       DocumentState::FromDataSource(GetMainFrame()->dataSource()));
2367   ASSERT_TRUE(provider);
2368   EXPECT_NE(provider1_id, provider->provider_id());
2369   extra_data = static_cast<RequestExtraData*>(
2370       GetMainFrame()->dataSource()->request().extraData());
2371   ASSERT_TRUE(extra_data);
2372   EXPECT_EQ(extra_data->service_worker_provider_id(),
2373             provider->provider_id());
2374
2375   // See that subresource requests are also tagged with the provider's id.
2376   EXPECT_EQ(frame(), RenderFrameImpl::FromWebFrame(GetMainFrame()));
2377   blink::WebURLRequest request(GURL("http://foo.com"));
2378   request.setRequestContext(blink::WebURLRequest::RequestContextSubresource);
2379   blink::WebURLResponse redirect_response;
2380   frame()->willSendRequest(GetMainFrame(), 0, request, redirect_response);
2381   extra_data = static_cast<RequestExtraData*>(request.extraData());
2382   ASSERT_TRUE(extra_data);
2383   EXPECT_EQ(extra_data->service_worker_provider_id(),
2384             provider->provider_id());
2385 }
2386
2387 TEST_F(RenderViewImplTest, OnSetAccessibilityMode) {
2388   ASSERT_EQ(AccessibilityModeOff, frame()->accessibility_mode());
2389   ASSERT_EQ((RendererAccessibility*) NULL, frame()->renderer_accessibility());
2390
2391   frame()->OnSetAccessibilityMode(AccessibilityModeTreeOnly);
2392   ASSERT_EQ(AccessibilityModeTreeOnly, frame()->accessibility_mode());
2393   ASSERT_NE((RendererAccessibility*) NULL, frame()->renderer_accessibility());
2394   ASSERT_EQ(RendererAccessibilityTypeComplete,
2395             frame()->renderer_accessibility()->GetType());
2396
2397   frame()->OnSetAccessibilityMode(AccessibilityModeOff);
2398   ASSERT_EQ(AccessibilityModeOff, frame()->accessibility_mode());
2399   ASSERT_EQ((RendererAccessibility*) NULL, frame()->renderer_accessibility());
2400
2401   frame()->OnSetAccessibilityMode(AccessibilityModeComplete);
2402   ASSERT_EQ(AccessibilityModeComplete, frame()->accessibility_mode());
2403   ASSERT_NE((RendererAccessibility*) NULL, frame()->renderer_accessibility());
2404   ASSERT_EQ(RendererAccessibilityTypeComplete,
2405             frame()->renderer_accessibility()->GetType());
2406
2407   frame()->OnSetAccessibilityMode(AccessibilityModeEditableTextOnly);
2408   ASSERT_EQ(AccessibilityModeEditableTextOnly, frame()->accessibility_mode());
2409   ASSERT_NE((RendererAccessibility*) NULL, frame()->renderer_accessibility());
2410   ASSERT_EQ(RendererAccessibilityTypeFocusOnly,
2411             frame()->renderer_accessibility()->GetType());
2412 }
2413
2414 TEST_F(RenderViewImplTest, ScreenMetricsEmulation) {
2415   LoadHTML("<body style='min-height:1000px;'></body>");
2416
2417   blink::WebDeviceEmulationParams params;
2418   base::string16 get_width = base::ASCIIToUTF16("Number(window.innerWidth)");
2419   base::string16 get_height = base::ASCIIToUTF16("Number(window.innerHeight)");
2420   int width, height;
2421
2422   params.viewSize.width = 327;
2423   params.viewSize.height = 415;
2424   view()->EnableScreenMetricsEmulation(params);
2425   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(get_width, &width));
2426   EXPECT_EQ(params.viewSize.width, width);
2427   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(get_height, &height));
2428   EXPECT_EQ(params.viewSize.height, height);
2429
2430   params.viewSize.width = 1005;
2431   params.viewSize.height = 1102;
2432   view()->EnableScreenMetricsEmulation(params);
2433   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(get_width, &width));
2434   EXPECT_EQ(params.viewSize.width, width);
2435   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(get_height, &height));
2436   EXPECT_EQ(params.viewSize.height, height);
2437
2438   view()->DisableScreenMetricsEmulation();
2439
2440   view()->EnableScreenMetricsEmulation(params);
2441   // Don't disable here to test that emulation is being shutdown properly.
2442 }
2443
2444 // Sanity checks for the Navigation Timing API |navigationStart| override. We
2445 // are asserting only most basic constraints, as TimeTicks (passed as the
2446 // override) are not comparable with the wall time (returned by the Blink API).
2447 TEST_F(RenderViewImplTest, NavigationStartOverride) {
2448   // Verify that a navigation that claims to have started at the earliest
2449   // possible TimeTicks is indeed reported as one that started before
2450   // OnNavigate() is called.
2451   base::Time before_navigation = base::Time::Now();
2452   FrameMsg_Navigate_Params early_nav_params;
2453   early_nav_params.url = GURL("data:text/html,<div>Page</div>");
2454   early_nav_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
2455   early_nav_params.transition = ui::PAGE_TRANSITION_TYPED;
2456   early_nav_params.page_id = -1;
2457   early_nav_params.is_post = true;
2458   early_nav_params.browser_navigation_start =
2459       base::TimeTicks::FromInternalValue(1);
2460
2461   frame()->OnNavigate(early_nav_params);
2462   ProcessPendingMessages();
2463
2464   base::Time early_nav_reported_start =
2465       base::Time::FromDoubleT(GetMainFrame()->performance().navigationStart());
2466   EXPECT_LT(early_nav_reported_start, before_navigation);
2467
2468   // Verify that a navigation that claims to have started in the future - 42
2469   // days from now is *not* reported as one that starts in the future; as we
2470   // sanitize the override allowing a maximum of ::Now().
2471   FrameMsg_Navigate_Params late_nav_params;
2472   late_nav_params.url = GURL("data:text/html,<div>Another page</div>");
2473   late_nav_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
2474   late_nav_params.transition = ui::PAGE_TRANSITION_TYPED;
2475   late_nav_params.page_id = -1;
2476   late_nav_params.is_post = true;
2477   late_nav_params.browser_navigation_start =
2478       base::TimeTicks::Now() + base::TimeDelta::FromDays(42);
2479
2480   frame()->OnNavigate(late_nav_params);
2481   ProcessPendingMessages();
2482   base::Time after_navigation =
2483       base::Time::Now() + base::TimeDelta::FromDays(1);
2484
2485   base::Time late_nav_reported_start =
2486       base::Time::FromDoubleT(GetMainFrame()->performance().navigationStart());
2487   EXPECT_LE(late_nav_reported_start, after_navigation);
2488 }
2489
2490 }  // namespace content