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.
5 #include "base/strings/string16.h"
6 #include "base/strings/string_util.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "content/public/browser/native_web_keyboard_event.h"
9 #include "content/public/common/web_preferences.h"
10 #include "content/public/test/render_view_test.h"
11 #include "content/renderer/render_view_impl.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "third_party/WebKit/public/web/WebLocalFrame.h"
15 #include <Carbon/Carbon.h> // for the kVK_* constants.
16 #include <Cocoa/Cocoa.h>
20 NSEvent* CmdDeadKeyEvent(NSEventType type, unsigned short code) {
24 uniChar = NSUpArrowFunctionKey;
27 uniChar = NSDownArrowFunctionKey;
32 NSString* s = [NSString stringWithFormat:@"%C", uniChar];
34 return [NSEvent keyEventWithType:type
36 modifierFlags:NSCommandKeyMask
41 charactersIgnoringModifiers:s
46 // Test that cmd-up/down scrolls the page exactly if it is not intercepted by
48 TEST_F(RenderViewTest, MacTestCmdUp) {
49 // Some preprocessor trickery so that we can have literal html in our source,
50 // makes it easier to copy html to and from an html file for testing (the
51 // preprocessor will remove the newlines at the line ends, turning this into
52 // a single long line).
54 const char* kRawHtml = HTML(
57 /* Add a vertical scrollbar */
58 body { height: 10128px; }
60 <div id='keydown'></div>
61 <div id='scroll'></div>
63 var allowKeyEvents = true;
64 var scroll = document.getElementById('scroll');
65 var result = document.getElementById('keydown');
66 onkeydown = function(event) {
69 event.shiftKey + ',' +
73 return allowKeyEvents;
77 TODO(esprehn): For some strange reason we need a non-empty document for
78 scrolling to work. This is not the case in a real browser only in the test.
85 prefs.enable_scroll_animator = false;
87 RenderViewImpl* view = static_cast<RenderViewImpl*>(view_);
88 view->OnUpdateWebPreferences(prefs);
90 const int kMaxOutputCharacters = 1024;
91 base::string16 output;
93 NSEvent* arrowDownKeyDown = CmdDeadKeyEvent(NSKeyDown, kVK_DownArrow);
94 NSEvent* arrowUpKeyDown = CmdDeadKeyEvent(NSKeyDown, kVK_UpArrow);
96 // First test when javascript does not eat keypresses -- should scroll.
97 view->set_send_content_state_immediately(true);
99 render_thread_->sink().ClearMessages();
101 const char* kArrowDownScrollDown = "40,false,false,true,false\n10144\np1";
102 view->OnSetEditCommandsForNextKeyEvent(
103 EditCommands(1, EditCommand("moveToEndOfDocument", "")));
104 SendNativeKeyEvent(NativeWebKeyboardEvent(arrowDownKeyDown));
105 ProcessPendingMessages();
106 ExecuteJavaScriptForTests("scroll.textContent = window.pageYOffset");
107 output = GetMainFrame()->contentAsText(kMaxOutputCharacters);
108 EXPECT_EQ(kArrowDownScrollDown, base::UTF16ToASCII(output));
110 const char* kArrowUpScrollUp = "38,false,false,true,false\n0\np1";
111 view->OnSetEditCommandsForNextKeyEvent(
112 EditCommands(1, EditCommand("moveToBeginningOfDocument", "")));
113 SendNativeKeyEvent(NativeWebKeyboardEvent(arrowUpKeyDown));
114 ProcessPendingMessages();
115 ExecuteJavaScriptForTests("scroll.textContent = window.pageYOffset");
116 output = GetMainFrame()->contentAsText(kMaxOutputCharacters);
117 EXPECT_EQ(kArrowUpScrollUp, base::UTF16ToASCII(output));
119 // Now let javascript eat the key events -- no scrolling should happen.
120 // Set a scroll position slightly down the page to ensure that it does not
122 ExecuteJavaScriptForTests("allowKeyEvents = false; window.scrollTo(0, 100)");
124 const char* kArrowDownNoScroll = "40,false,false,true,false\n100\np1";
125 view->OnSetEditCommandsForNextKeyEvent(
126 EditCommands(1, EditCommand("moveToEndOfDocument", "")));
127 SendNativeKeyEvent(NativeWebKeyboardEvent(arrowDownKeyDown));
128 ProcessPendingMessages();
129 ExecuteJavaScriptForTests("scroll.textContent = window.pageYOffset");
130 output = GetMainFrame()->contentAsText(kMaxOutputCharacters);
131 EXPECT_EQ(kArrowDownNoScroll, base::UTF16ToASCII(output));
133 const char* kArrowUpNoScroll = "38,false,false,true,false\n100\np1";
134 view->OnSetEditCommandsForNextKeyEvent(
135 EditCommands(1, EditCommand("moveToBeginningOfDocument", "")));
136 SendNativeKeyEvent(NativeWebKeyboardEvent(arrowUpKeyDown));
137 ProcessPendingMessages();
138 ExecuteJavaScriptForTests("scroll.textContent = window.pageYOffset");
139 output = GetMainFrame()->contentAsText(kMaxOutputCharacters);
140 EXPECT_EQ(kArrowUpNoScroll, base::UTF16ToASCII(output));
143 } // namespace content