| 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 |