Home | History | Annotate | Download | only in renderer
      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 class RenderViewImplInitialSizeTest : public RenderViewImplTest {
   2491  public:
   2492   RenderViewImplInitialSizeTest()
   2493       : RenderViewImplTest(), initial_size_(200, 100) {}
   2494 
   2495  protected:
   2496   virtual scoped_ptr<ViewMsg_Resize_Params> InitialSizeParams() override {
   2497     scoped_ptr<ViewMsg_Resize_Params> initial_size_params(
   2498         new ViewMsg_Resize_Params());
   2499     initial_size_params->new_size = initial_size_;
   2500     return initial_size_params.Pass();
   2501   }
   2502 
   2503   gfx::Size initial_size_;
   2504 };
   2505 
   2506 TEST_F(RenderViewImplInitialSizeTest, InitialSize) {
   2507   ASSERT_EQ(initial_size_, view_->GetSize());
   2508   ASSERT_EQ(initial_size_, gfx::Size(view_->GetWebView()->size()));
   2509 }
   2510 
   2511 }  // namespace content
   2512