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