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