OLD | NEW |
| (Empty) |
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 "webkit/tools/test_shell/test_webview_delegate.h" | |
6 | |
7 #import <Cocoa/Cocoa.h> | |
8 #include "base/strings/sys_string_conversions.h" | |
9 #include "base/utf_string_conversions.h" | |
10 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h" | |
11 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPopupMenu.h" | |
12 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" | |
13 #include "webkit/glue/webcursor.h" | |
14 #include "webkit/glue/webmenurunner_mac.h" | |
15 #include "webkit/plugins/npapi/plugin_list.h" | |
16 #include "webkit/plugins/npapi/webplugin_delegate_impl.h" | |
17 #include "webkit/tools/test_shell/test_shell.h" | |
18 | |
19 using webkit::npapi::WebPluginDelegateImpl; | |
20 using WebKit::WebCursorInfo; | |
21 using WebKit::WebNavigationPolicy; | |
22 using WebKit::WebPopupMenu; | |
23 using WebKit::WebPopupMenuInfo; | |
24 using WebKit::WebRect; | |
25 using WebKit::WebWidget; | |
26 | |
27 namespace { | |
28 | |
29 // Helper function for manufacturing input events to send to WebKit. | |
30 NSEvent* EventWithMenuAction(BOOL item_chosen, int window_num, | |
31 int item_height, int selected_index, | |
32 NSRect menu_bounds, NSRect view_bounds) { | |
33 NSEvent* event = nil; | |
34 double event_time = (double)(AbsoluteToDuration(UpTime())) / 1000.0; | |
35 | |
36 if (item_chosen) { | |
37 // Construct a mouse up event to simulate the selection of an appropriate | |
38 // menu item. | |
39 NSPoint click_pos; | |
40 click_pos.x = menu_bounds.size.width / 2; | |
41 | |
42 // This is going to be hard to calculate since the button is painted by | |
43 // WebKit, the menu by Cocoa, and we have to translate the selected_item | |
44 // index to a coordinate that WebKit's PopupMenu expects which uses a | |
45 // different font *and* expects to draw the menu below the button like we do | |
46 // on Windows. | |
47 // The WebKit popup menu thinks it will draw just below the button, so | |
48 // create the click at the offset based on the selected item's index and | |
49 // account for the different coordinate system used by NSView. | |
50 int item_offset = selected_index * item_height + item_height / 2; | |
51 click_pos.y = view_bounds.size.height - item_offset; | |
52 event = [NSEvent mouseEventWithType:NSLeftMouseUp | |
53 location:click_pos | |
54 modifierFlags:0 | |
55 timestamp:event_time | |
56 windowNumber:window_num | |
57 context:nil | |
58 eventNumber:0 | |
59 clickCount:1 | |
60 pressure:1.0]; | |
61 } else { | |
62 // Fake an ESC key event (keyCode = 0x1B, from webinputevent_mac.mm) and | |
63 // forward that to WebKit. | |
64 NSPoint key_pos; | |
65 key_pos.x = 0; | |
66 key_pos.y = 0; | |
67 NSString* escape_str = [NSString stringWithFormat:@"%c", 0x1B]; | |
68 event = [NSEvent keyEventWithType:NSKeyDown | |
69 location:key_pos | |
70 modifierFlags:0 | |
71 timestamp:event_time | |
72 windowNumber:window_num | |
73 context:nil | |
74 characters:@"" | |
75 charactersIgnoringModifiers:escape_str | |
76 isARepeat:NO | |
77 keyCode:0x1B]; | |
78 } | |
79 | |
80 return event; | |
81 } | |
82 | |
83 } // namespace | |
84 | |
85 // WebViewClient -------------------------------------------------------------- | |
86 | |
87 WebWidget* TestWebViewDelegate::createPopupMenu( | |
88 const WebPopupMenuInfo& info) { | |
89 WebWidget* webwidget = shell_->CreatePopupWidget(); | |
90 popup_menu_info_.reset(new WebPopupMenuInfo(info)); | |
91 return webwidget; | |
92 } | |
93 | |
94 // WebWidgetClient ------------------------------------------------------------ | |
95 | |
96 void TestWebViewDelegate::show(WebNavigationPolicy policy) { | |
97 if (!popup_menu_info_.get()) | |
98 return; | |
99 if (this != shell_->popup_delegate()) | |
100 return; | |
101 // Display a HTML select menu. | |
102 | |
103 std::vector<WebMenuItem> items; | |
104 for (size_t i = 0; i < popup_menu_info_->items.size(); ++i) | |
105 items.push_back(popup_menu_info_->items[i]); | |
106 | |
107 int item_height = popup_menu_info_->itemHeight; | |
108 double font_size = popup_menu_info_->itemFontSize; | |
109 int selected_index = popup_menu_info_->selectedIndex; | |
110 bool right_aligned = popup_menu_info_->rightAligned; | |
111 popup_menu_info_.reset(); // No longer needed. | |
112 | |
113 const WebRect& bounds = popup_bounds_; | |
114 | |
115 // Set up the menu position. | |
116 NSView* web_view = shell_->webViewWnd(); | |
117 NSRect view_rect = [web_view bounds]; | |
118 int y_offset = bounds.y + bounds.height; | |
119 NSRect position = NSMakeRect(bounds.x, view_rect.size.height - y_offset, | |
120 bounds.width, bounds.height); | |
121 | |
122 // Display the menu. | |
123 scoped_nsobject<WebMenuRunner> menu_runner; | |
124 menu_runner.reset([[WebMenuRunner alloc] initWithItems:items | |
125 fontSize:font_size | |
126 rightAligned:right_aligned]); | |
127 | |
128 [menu_runner runMenuInView:shell_->webViewWnd() | |
129 withBounds:position | |
130 initialIndex:selected_index]; | |
131 | |
132 // Get the selected item and forward to WebKit. WebKit expects an input event | |
133 // (mouse down, keyboard activity) for this, so we calculate the proper | |
134 // position based on the selected index and provided bounds. | |
135 WebWidgetHost* popup = shell_->popupHost(); | |
136 int window_num = [shell_->mainWnd() windowNumber]; | |
137 NSEvent* event = EventWithMenuAction([menu_runner menuItemWasChosen], | |
138 window_num, item_height, | |
139 [menu_runner indexOfSelectedItem], | |
140 position, view_rect); | |
141 | |
142 if ([menu_runner menuItemWasChosen]) { | |
143 // Construct a mouse up event to simulate the selection of an appropriate | |
144 // menu item. | |
145 popup->MouseEvent(event); | |
146 } else { | |
147 // Fake an ESC key event (keyCode = 0x1B, from webinputevent_mac.mm) and | |
148 // forward that to WebKit. | |
149 popup->KeyEvent(event); | |
150 } | |
151 } | |
152 | |
153 void TestWebViewDelegate::closeWidgetSoon() { | |
154 if (this == shell_->delegate()) { | |
155 NSWindow *win = shell_->mainWnd(); | |
156 [win performSelector:@selector(performClose:) withObject:nil afterDelay:0]; | |
157 } else if (this == shell_->popup_delegate()) { | |
158 shell_->ClosePopup(); | |
159 } | |
160 } | |
161 | |
162 void TestWebViewDelegate::didChangeCursor(const WebCursorInfo& cursor_info) { | |
163 NSCursor* ns_cursor = WebCursor(cursor_info).GetNativeCursor(); | |
164 [ns_cursor set]; | |
165 } | |
166 | |
167 WebRect TestWebViewDelegate::windowRect() { | |
168 if (WebWidgetHost* host = GetWidgetHost()) { | |
169 NSView *view = host->view_handle(); | |
170 NSRect rect = [view frame]; | |
171 return gfx::Rect(NSRectToCGRect(rect)); | |
172 } | |
173 return WebRect(); | |
174 } | |
175 | |
176 void TestWebViewDelegate::setWindowRect(const WebRect& rect) { | |
177 if (this == shell_->delegate()) { | |
178 set_fake_window_rect(rect); | |
179 } else if (this == shell_->popup_delegate()) { | |
180 popup_bounds_ = rect; // The initial position of the popup. | |
181 } | |
182 } | |
183 | |
184 WebRect TestWebViewDelegate::rootWindowRect() { | |
185 if (using_fake_rect_) { | |
186 return fake_window_rect(); | |
187 } | |
188 if (WebWidgetHost* host = GetWidgetHost()) { | |
189 NSView *view = host->view_handle(); | |
190 NSRect rect = [[[view window] contentView] frame]; | |
191 return gfx::Rect(NSRectToCGRect(rect)); | |
192 } | |
193 return WebRect(); | |
194 } | |
195 | |
196 @interface NSWindow(OSInternals) | |
197 - (NSRect)_growBoxRect; | |
198 @end | |
199 | |
200 WebRect TestWebViewDelegate::windowResizerRect() { | |
201 NSRect resize_rect = NSMakeRect(0, 0, 0, 0); | |
202 WebWidgetHost* host = GetWidgetHost(); | |
203 // To match the WebKit screen shots, we need the resize area to overlap | |
204 // the scroll arrows, so in layout test mode, we don't return a real rect. | |
205 if (!(shell_->layout_test_mode()) && host) { | |
206 NSView *view = host->view_handle(); | |
207 NSWindow* window = [view window]; | |
208 resize_rect = [window _growBoxRect]; | |
209 // The scrollbar assumes that the resizer goes all the way down to the | |
210 // bottom corner, so we ignore any y offset to the rect itself and use the | |
211 // entire bottom corner. | |
212 resize_rect.origin.y = 0; | |
213 // Convert to view coordinates from window coordinates. | |
214 resize_rect = [view convertRect:resize_rect fromView:nil]; | |
215 // Flip the rect in view coordinates | |
216 resize_rect.origin.y = | |
217 [view frame].size.height - resize_rect.origin.y - | |
218 resize_rect.size.height; | |
219 } | |
220 return gfx::Rect(NSRectToCGRect(resize_rect)); | |
221 } | |
222 | |
223 void TestWebViewDelegate::runModal() { | |
224 NOTIMPLEMENTED(); | |
225 } | |
226 | |
227 // WebPluginPageDelegate ------------------------------------------------------ | |
228 | |
229 webkit::npapi::WebPluginDelegate* TestWebViewDelegate::CreatePluginDelegate( | |
230 const base::FilePath& path, | |
231 const std::string& mime_type) { | |
232 WebWidgetHost *host = GetWidgetHost(); | |
233 if (!host) | |
234 return NULL; | |
235 | |
236 WebPluginDelegateImpl* delegate = | |
237 WebPluginDelegateImpl::Create(path, mime_type); | |
238 if (delegate) | |
239 delegate->SetNoBufferContext(); | |
240 return delegate; | |
241 } | |
242 | |
243 void TestWebViewDelegate::CreatedPluginWindow( | |
244 gfx::PluginWindowHandle handle) { | |
245 } | |
246 | |
247 void TestWebViewDelegate::WillDestroyPluginWindow( | |
248 gfx::PluginWindowHandle handle) { | |
249 } | |
250 | |
251 void TestWebViewDelegate::DidMovePlugin( | |
252 const webkit::npapi::WebPluginGeometry& move) { | |
253 // TODO(port): add me once plugins work. | |
254 } | |
255 | |
256 // Public methods ------------------------------------------------------------- | |
257 | |
258 void TestWebViewDelegate::UpdateSelectionClipboard(bool is_empty_selection) { | |
259 // No selection clipboard on mac, do nothing. | |
260 } | |
261 | |
262 // Private methods ------------------------------------------------------------ | |
263 | |
264 void TestWebViewDelegate::ShowJavaScriptAlert(const base::string16& message) { | |
265 NSString *text = | |
266 [NSString stringWithUTF8String:UTF16ToUTF8(message).c_str()]; | |
267 NSAlert *alert = [NSAlert alertWithMessageText:@"JavaScript Alert" | |
268 defaultButton:@"OK" | |
269 alternateButton:nil | |
270 otherButton:nil | |
271 informativeTextWithFormat:@"%@", text]; | |
272 [alert runModal]; | |
273 } | |
274 | |
275 void TestWebViewDelegate::SetPageTitle(const base::string16& title) { | |
276 [[shell_->webViewHost()->view_handle() window] | |
277 setTitle:[NSString stringWithUTF8String:UTF16ToUTF8(title).c_str()]]; | |
278 } | |
279 | |
280 void TestWebViewDelegate::SetAddressBarURL(const GURL& url) { | |
281 const char* frameURL = url.spec().c_str(); | |
282 NSString *address = [NSString stringWithUTF8String:frameURL]; | |
283 [shell_->editWnd() setStringValue:address]; | |
284 } | |
OLD | NEW |