// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/strings/string16.h" #include "base/strings/string_util.h" #include "content/public/browser/native_web_keyboard_event.h" #include "content/public/test/render_view_test.h" #include "content/renderer/render_view_impl.h" #include "testing/gtest/include/gtest/gtest.h" #include "webkit/common/webpreferences.h" #include <Cocoa/Cocoa.h> #include <Carbon/Carbon.h> // for the kVK_* constants. namespace content { NSEvent* CmdDeadKeyEvent(NSEventType type, unsigned short code) { UniChar uniChar = 0; switch(code) { case kVK_UpArrow: uniChar = NSUpArrowFunctionKey; break; case kVK_DownArrow: uniChar = NSDownArrowFunctionKey; break; default: CHECK(false); } NSString* s = [NSString stringWithFormat:@"%C", uniChar]; return [NSEvent keyEventWithType:type location:NSZeroPoint modifierFlags:NSCommandKeyMask timestamp:0.0 windowNumber:0 context:nil characters:s charactersIgnoringModifiers:s isARepeat:NO keyCode:code]; } // Test that cmd-up/down scrolls the page exactly if it is not intercepted by // javascript. TEST_F(RenderViewTest, MacTestCmdUp) { // Some preprocessor trickery so that we can have literal html in our source, // makes it easier to copy html to and from an html file for testing (the // preprocessor will remove the newlines at the line ends, turning this into // a single long line). #define HTML(s) #s const char* kRawHtml = HTML( <!DOCTYPE html> <style> /* Add a vertical scrollbar */ body { height: 10128px; } </style> <div id='keydown'></div> <div id='scroll'></div> <script> var allowKeyEvents = true; var scroll = document.getElementById('scroll'); var result = document.getElementById('keydown'); onkeydown = function(event) { result.textContent = event.keyCode + ',' + event.shiftKey + ',' + event.ctrlKey + ',' + event.metaKey + ',' + event.altKey; return allowKeyEvents; } </script> <!-- TODO(esprehn): For some strange reason we need a non-empty document for scrolling to work. This is not the case in a real browser only in the test. --> <p>p1 ); #undef HTML WebPreferences prefs; prefs.enable_scroll_animator = false; RenderViewImpl* view = static_cast<RenderViewImpl*>(view_); view->OnUpdateWebPreferences(prefs); const int kMaxOutputCharacters = 1024; base::string16 output; NSEvent* arrowDownKeyDown = CmdDeadKeyEvent(NSKeyDown, kVK_DownArrow); NSEvent* arrowUpKeyDown = CmdDeadKeyEvent(NSKeyDown, kVK_UpArrow); // First test when javascript does not eat keypresses -- should scroll. view->set_send_content_state_immediately(true); LoadHTML(kRawHtml); render_thread_->sink().ClearMessages(); const char* kArrowDownScrollDown = "40,false,false,true,false\n10144\np1"; view->OnSetEditCommandsForNextKeyEvent( EditCommands(1, EditCommand("moveToEndOfDocument", ""))); SendNativeKeyEvent(NativeWebKeyboardEvent(arrowDownKeyDown)); ProcessPendingMessages(); ExecuteJavaScript("scroll.textContent = window.pageYOffset"); output = GetMainFrame()->contentAsText(kMaxOutputCharacters); EXPECT_EQ(kArrowDownScrollDown, UTF16ToASCII(output)); const char* kArrowUpScrollUp = "38,false,false,true,false\n0\np1"; view->OnSetEditCommandsForNextKeyEvent( EditCommands(1, EditCommand("moveToBeginningOfDocument", ""))); SendNativeKeyEvent(NativeWebKeyboardEvent(arrowUpKeyDown)); ProcessPendingMessages(); ExecuteJavaScript("scroll.textContent = window.pageYOffset"); output = GetMainFrame()->contentAsText(kMaxOutputCharacters); EXPECT_EQ(kArrowUpScrollUp, UTF16ToASCII(output)); // Now let javascript eat the key events -- no scrolling should happen. // Set a scroll position slightly down the page to ensure that it does not // move. ExecuteJavaScript("allowKeyEvents = false; window.scrollTo(0, 100)"); const char* kArrowDownNoScroll = "40,false,false,true,false\n100\np1"; view->OnSetEditCommandsForNextKeyEvent( EditCommands(1, EditCommand("moveToEndOfDocument", ""))); SendNativeKeyEvent(NativeWebKeyboardEvent(arrowDownKeyDown)); ProcessPendingMessages(); ExecuteJavaScript("scroll.textContent = window.pageYOffset"); output = GetMainFrame()->contentAsText(kMaxOutputCharacters); EXPECT_EQ(kArrowDownNoScroll, UTF16ToASCII(output)); const char* kArrowUpNoScroll = "38,false,false,true,false\n100\np1"; view->OnSetEditCommandsForNextKeyEvent( EditCommands(1, EditCommand("moveToBeginningOfDocument", ""))); SendNativeKeyEvent(NativeWebKeyboardEvent(arrowUpKeyDown)); ProcessPendingMessages(); ExecuteJavaScript("scroll.textContent = window.pageYOffset"); output = GetMainFrame()->contentAsText(kMaxOutputCharacters); EXPECT_EQ(kArrowUpNoScroll, UTF16ToASCII(output)); } } // namespace content