1 /* 2 * Copyright (C) 2009 Google Inc. All rights reserved. 3 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * * Neither the name of Google Inc. nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include "config.h" 33 #include "web/ChromeClientImpl.h" 34 35 #include "bindings/core/v8/ScriptController.h" 36 #include "core/HTMLNames.h" 37 #include "core/accessibility/AXObject.h" 38 #include "core/accessibility/AXObjectCache.h" 39 #include "core/dom/Document.h" 40 #include "core/dom/Fullscreen.h" 41 #include "core/dom/Node.h" 42 #include "core/events/KeyboardEvent.h" 43 #include "core/events/MouseEvent.h" 44 #include "core/events/WheelEvent.h" 45 #include "core/frame/Console.h" 46 #include "core/frame/FrameView.h" 47 #include "core/frame/Settings.h" 48 #include "core/html/HTMLInputElement.h" 49 #include "core/html/forms/ColorChooser.h" 50 #include "core/html/forms/ColorChooserClient.h" 51 #include "core/html/forms/DateTimeChooser.h" 52 #include "core/loader/DocumentLoader.h" 53 #include "core/loader/FrameLoadRequest.h" 54 #include "core/page/Page.h" 55 #include "core/page/PagePopupDriver.h" 56 #include "core/page/WindowFeatures.h" 57 #include "core/rendering/HitTestResult.h" 58 #include "core/rendering/RenderPart.h" 59 #include "core/rendering/RenderWidget.h" 60 #include "core/rendering/compositing/CompositedSelectionBound.h" 61 #include "platform/Cursor.h" 62 #include "platform/FileChooser.h" 63 #include "platform/NotImplemented.h" 64 #include "platform/PlatformScreen.h" 65 #include "platform/RuntimeEnabledFeatures.h" 66 #include "platform/exported/WrappedResourceRequest.h" 67 #include "platform/geometry/FloatRect.h" 68 #include "platform/geometry/IntRect.h" 69 #include "platform/graphics/GraphicsLayer.h" 70 #include "platform/weborigin/SecurityOrigin.h" 71 #include "public/platform/Platform.h" 72 #include "public/platform/WebCursorInfo.h" 73 #include "public/platform/WebRect.h" 74 #include "public/platform/WebSelectionBound.h" 75 #include "public/platform/WebURLRequest.h" 76 #include "public/web/WebAXObject.h" 77 #include "public/web/WebAutofillClient.h" 78 #include "public/web/WebColorChooser.h" 79 #include "public/web/WebColorSuggestion.h" 80 #include "public/web/WebConsoleMessage.h" 81 #include "public/web/WebFrameClient.h" 82 #include "public/web/WebInputElement.h" 83 #include "public/web/WebInputEvent.h" 84 #include "public/web/WebKit.h" 85 #include "public/web/WebNode.h" 86 #include "public/web/WebPlugin.h" 87 #include "public/web/WebPopupMenuInfo.h" 88 #include "public/web/WebSettings.h" 89 #include "public/web/WebTextDirection.h" 90 #include "public/web/WebTouchAction.h" 91 #include "public/web/WebUserGestureIndicator.h" 92 #include "public/web/WebUserGestureToken.h" 93 #include "public/web/WebViewClient.h" 94 #include "public/web/WebWindowFeatures.h" 95 #include "web/ColorChooserPopupUIController.h" 96 #include "web/ColorChooserUIController.h" 97 #include "web/DateTimeChooserImpl.h" 98 #include "web/ExternalDateTimeChooser.h" 99 #include "web/ExternalPopupMenu.h" 100 #include "web/PopupMenuChromium.h" 101 #include "web/WebFileChooserCompletionImpl.h" 102 #include "web/WebInputEventConversion.h" 103 #include "web/WebLocalFrameImpl.h" 104 #include "web/WebPluginContainerImpl.h" 105 #include "web/WebPopupMenuImpl.h" 106 #include "web/WebSettingsImpl.h" 107 #include "web/WebViewImpl.h" 108 #include "wtf/text/CString.h" 109 #include "wtf/text/StringBuilder.h" 110 #include "wtf/text/StringConcatenate.h" 111 #include "wtf/unicode/CharacterNames.h" 112 113 namespace blink { 114 115 // Converts a AXObjectCache::AXNotification to a WebAXEvent 116 static WebAXEvent toWebAXEvent(AXObjectCache::AXNotification notification) 117 { 118 // These enums have the same values; enforced in AssertMatchingEnums.cpp. 119 return static_cast<WebAXEvent>(notification); 120 } 121 122 static WebSelectionBound toWebSelectionBound(const CompositedSelectionBound& bound) 123 { 124 ASSERT(bound.layer); 125 126 // These enums have the same values; enforced in AssertMatchingEnums.cpp. 127 WebSelectionBound result(static_cast<WebSelectionBound::Type>(bound.type)); 128 result.layerId = bound.layer->platformLayer()->id(); 129 result.edgeTopInLayer = roundedIntPoint(bound.edgeTopInLayer); 130 result.edgeBottomInLayer = roundedIntPoint(bound.edgeBottomInLayer); 131 return result; 132 } 133 134 ChromeClientImpl::ChromeClientImpl(WebViewImpl* webView) 135 : m_webView(webView) 136 , m_toolbarsVisible(true) 137 , m_statusbarVisible(true) 138 , m_scrollbarsVisible(true) 139 , m_menubarVisible(true) 140 , m_resizable(true) 141 , m_pagePopupDriver(webView) 142 { 143 } 144 145 ChromeClientImpl::~ChromeClientImpl() 146 { 147 } 148 149 void* ChromeClientImpl::webView() const 150 { 151 return static_cast<void*>(m_webView); 152 } 153 154 void ChromeClientImpl::chromeDestroyed() 155 { 156 // Our lifetime is bound to the WebViewImpl. 157 } 158 159 void ChromeClientImpl::setWindowRect(const FloatRect& r) 160 { 161 if (m_webView->client()) 162 m_webView->client()->setWindowRect(IntRect(r)); 163 } 164 165 FloatRect ChromeClientImpl::windowRect() 166 { 167 WebRect rect; 168 if (m_webView->client()) 169 rect = m_webView->client()->rootWindowRect(); 170 else { 171 // These numbers will be fairly wrong. The window's x/y coordinates will 172 // be the top left corner of the screen and the size will be the content 173 // size instead of the window size. 174 rect.width = m_webView->size().width; 175 rect.height = m_webView->size().height; 176 } 177 return FloatRect(rect); 178 } 179 180 FloatRect ChromeClientImpl::pageRect() 181 { 182 // We hide the details of the window's border thickness from the web page by 183 // simple re-using the window position here. So, from the point-of-view of 184 // the web page, the window has no border. 185 return windowRect(); 186 } 187 188 void ChromeClientImpl::focus() 189 { 190 if (m_webView->client()) 191 m_webView->client()->didFocus(); 192 } 193 194 bool ChromeClientImpl::canTakeFocus(FocusType) 195 { 196 // For now the browser can always take focus if we're not running layout 197 // tests. 198 return !layoutTestMode(); 199 } 200 201 void ChromeClientImpl::takeFocus(FocusType type) 202 { 203 if (!m_webView->client()) 204 return; 205 if (type == FocusTypeBackward) 206 m_webView->client()->focusPrevious(); 207 else 208 m_webView->client()->focusNext(); 209 } 210 211 void ChromeClientImpl::focusedNodeChanged(Node* node) 212 { 213 m_webView->client()->focusedNodeChanged(WebNode(node)); 214 215 WebURL focusURL; 216 if (node && node->isElementNode() && toElement(node)->isLiveLink()) 217 focusURL = toElement(node)->hrefURL(); 218 m_webView->client()->setKeyboardFocusURL(focusURL); 219 } 220 221 void ChromeClientImpl::focusedFrameChanged(LocalFrame* frame) 222 { 223 WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(frame); 224 if (webframe && webframe->client()) 225 webframe->client()->frameFocused(); 226 } 227 228 Page* ChromeClientImpl::createWindow(LocalFrame* frame, const FrameLoadRequest& r, const WindowFeatures& features, 229 NavigationPolicy navigationPolicy, ShouldSendReferrer shouldSendReferrer) 230 { 231 if (!m_webView->client()) 232 return 0; 233 234 WebNavigationPolicy policy = static_cast<WebNavigationPolicy>(navigationPolicy); 235 if (policy == WebNavigationPolicyIgnore) 236 policy = getNavigationPolicy(); 237 238 ASSERT(frame->document()); 239 Fullscreen::fullyExitFullscreen(*frame->document()); 240 241 WebViewImpl* newView = toWebViewImpl( 242 m_webView->client()->createView(WebLocalFrameImpl::fromFrame(frame), WrappedResourceRequest(r.resourceRequest()), features, r.frameName(), policy, shouldSendReferrer == NeverSendReferrer)); 243 if (!newView) 244 return 0; 245 return newView->page(); 246 } 247 248 static inline void updatePolicyForEvent(const WebInputEvent* inputEvent, NavigationPolicy* policy) 249 { 250 if (!inputEvent || inputEvent->type != WebInputEvent::MouseUp) 251 return; 252 253 const WebMouseEvent* mouseEvent = static_cast<const WebMouseEvent*>(inputEvent); 254 255 unsigned short buttonNumber; 256 switch (mouseEvent->button) { 257 case WebMouseEvent::ButtonLeft: 258 buttonNumber = 0; 259 break; 260 case WebMouseEvent::ButtonMiddle: 261 buttonNumber = 1; 262 break; 263 case WebMouseEvent::ButtonRight: 264 buttonNumber = 2; 265 break; 266 default: 267 return; 268 } 269 bool ctrl = mouseEvent->modifiers & WebMouseEvent::ControlKey; 270 bool shift = mouseEvent->modifiers & WebMouseEvent::ShiftKey; 271 bool alt = mouseEvent->modifiers & WebMouseEvent::AltKey; 272 bool meta = mouseEvent->modifiers & WebMouseEvent::MetaKey; 273 274 NavigationPolicy userPolicy = *policy; 275 navigationPolicyFromMouseEvent(buttonNumber, ctrl, shift, alt, meta, &userPolicy); 276 // User and app agree that we want a new window; let the app override the decorations. 277 if (userPolicy == NavigationPolicyNewWindow && *policy == NavigationPolicyNewPopup) 278 return; 279 *policy = userPolicy; 280 } 281 282 WebNavigationPolicy ChromeClientImpl::getNavigationPolicy() 283 { 284 // If our default configuration was modified by a script or wasn't 285 // created by a user gesture, then show as a popup. Else, let this 286 // new window be opened as a toplevel window. 287 bool asPopup = !m_toolbarsVisible 288 || !m_statusbarVisible 289 || !m_scrollbarsVisible 290 || !m_menubarVisible 291 || !m_resizable; 292 293 NavigationPolicy policy = NavigationPolicyNewForegroundTab; 294 if (asPopup) 295 policy = NavigationPolicyNewPopup; 296 updatePolicyForEvent(WebViewImpl::currentInputEvent(), &policy); 297 298 return static_cast<WebNavigationPolicy>(policy); 299 } 300 301 void ChromeClientImpl::show(NavigationPolicy navigationPolicy) 302 { 303 if (!m_webView->client()) 304 return; 305 306 WebNavigationPolicy policy = static_cast<WebNavigationPolicy>(navigationPolicy); 307 if (policy == WebNavigationPolicyIgnore) 308 policy = getNavigationPolicy(); 309 m_webView->client()->show(policy); 310 } 311 312 bool ChromeClientImpl::canRunModal() 313 { 314 return !!m_webView->client(); 315 } 316 317 void ChromeClientImpl::runModal() 318 { 319 if (m_webView->client()) 320 m_webView->client()->runModal(); 321 } 322 323 void ChromeClientImpl::setToolbarsVisible(bool value) 324 { 325 m_toolbarsVisible = value; 326 } 327 328 bool ChromeClientImpl::toolbarsVisible() 329 { 330 return m_toolbarsVisible; 331 } 332 333 void ChromeClientImpl::setStatusbarVisible(bool value) 334 { 335 m_statusbarVisible = value; 336 } 337 338 bool ChromeClientImpl::statusbarVisible() 339 { 340 return m_statusbarVisible; 341 } 342 343 void ChromeClientImpl::setScrollbarsVisible(bool value) 344 { 345 m_scrollbarsVisible = value; 346 WebLocalFrameImpl* webFrame = toWebLocalFrameImpl(m_webView->mainFrame()); 347 if (webFrame) 348 webFrame->setCanHaveScrollbars(value); 349 } 350 351 bool ChromeClientImpl::scrollbarsVisible() 352 { 353 return m_scrollbarsVisible; 354 } 355 356 void ChromeClientImpl::setMenubarVisible(bool value) 357 { 358 m_menubarVisible = value; 359 } 360 361 bool ChromeClientImpl::menubarVisible() 362 { 363 return m_menubarVisible; 364 } 365 366 void ChromeClientImpl::setResizable(bool value) 367 { 368 m_resizable = value; 369 } 370 371 bool ChromeClientImpl::shouldReportDetailedMessageForSource(const String& url) 372 { 373 WebLocalFrameImpl* webframe = m_webView->localFrameRootTemporary(); 374 return webframe->client() && webframe->client()->shouldReportDetailedMessageForSource(url); 375 } 376 377 void ChromeClientImpl::addMessageToConsole(LocalFrame* localFrame, MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceID, const String& stackTrace) 378 { 379 WebLocalFrameImpl* frame = WebLocalFrameImpl::fromFrame(localFrame); 380 if (frame && frame->client()) { 381 frame->client()->didAddMessageToConsole( 382 WebConsoleMessage(static_cast<WebConsoleMessage::Level>(level), message), 383 sourceID, 384 lineNumber, 385 stackTrace); 386 } 387 } 388 389 bool ChromeClientImpl::canRunBeforeUnloadConfirmPanel() 390 { 391 return !!m_webView->client(); 392 } 393 394 bool ChromeClientImpl::runBeforeUnloadConfirmPanel(const String& message, LocalFrame* frame) 395 { 396 WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(frame); 397 398 bool isReload = false; 399 WebDataSource* ds = webframe->provisionalDataSource(); 400 if (ds) 401 isReload = (ds->navigationType() == WebNavigationTypeReload); 402 403 if (webframe->client()) 404 return webframe->client()->runModalBeforeUnloadDialog(isReload, message); 405 return false; 406 } 407 408 void ChromeClientImpl::closeWindowSoon() 409 { 410 // Make sure this Page can no longer be found by JS. 411 Page::ordinaryPages().remove(m_webView->page()); 412 413 // Make sure that all loading is stopped. Ensures that JS stops executing! 414 m_webView->mainFrame()->stopLoading(); 415 416 if (m_webView->client()) 417 m_webView->client()->closeWidgetSoon(); 418 } 419 420 // Although a LocalFrame is passed in, we don't actually use it, since we 421 // already know our own m_webView. 422 void ChromeClientImpl::runJavaScriptAlert(LocalFrame* frame, const String& message) 423 { 424 WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(frame); 425 if (webframe->client()) { 426 if (WebUserGestureIndicator::isProcessingUserGesture()) 427 WebUserGestureIndicator::currentUserGestureToken().setJavascriptPrompt(); 428 webframe->client()->runModalAlertDialog(message); 429 } 430 } 431 432 // See comments for runJavaScriptAlert(). 433 bool ChromeClientImpl::runJavaScriptConfirm(LocalFrame* frame, const String& message) 434 { 435 WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(frame); 436 if (webframe->client()) { 437 if (WebUserGestureIndicator::isProcessingUserGesture()) 438 WebUserGestureIndicator::currentUserGestureToken().setJavascriptPrompt(); 439 return webframe->client()->runModalConfirmDialog(message); 440 } 441 return false; 442 } 443 444 // See comments for runJavaScriptAlert(). 445 bool ChromeClientImpl::runJavaScriptPrompt(LocalFrame* frame, 446 const String& message, 447 const String& defaultValue, 448 String& result) 449 { 450 WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(frame); 451 if (webframe->client()) { 452 if (WebUserGestureIndicator::isProcessingUserGesture()) 453 WebUserGestureIndicator::currentUserGestureToken().setJavascriptPrompt(); 454 WebString actualValue; 455 bool ok = webframe->client()->runModalPromptDialog( 456 message, 457 defaultValue, 458 &actualValue); 459 if (ok) 460 result = actualValue; 461 return ok; 462 } 463 return false; 464 } 465 466 void ChromeClientImpl::setStatusbarText(const String& message) 467 { 468 if (m_webView->client()) 469 m_webView->client()->setStatusText(message); 470 } 471 472 bool ChromeClientImpl::tabsToLinks() 473 { 474 return m_webView->tabsToLinks(); 475 } 476 477 IntRect ChromeClientImpl::windowResizerRect() const 478 { 479 IntRect result; 480 if (m_webView->client()) 481 result = m_webView->client()->windowResizerRect(); 482 return result; 483 } 484 485 void ChromeClientImpl::invalidateContentsAndRootView(const IntRect& updateRect) 486 { 487 if (updateRect.isEmpty()) 488 return; 489 m_webView->invalidateRect(updateRect); 490 } 491 492 void ChromeClientImpl::invalidateContentsForSlowScroll(const IntRect& updateRect) 493 { 494 invalidateContentsAndRootView(updateRect); 495 } 496 497 void ChromeClientImpl::scheduleAnimation() 498 { 499 m_webView->scheduleAnimation(); 500 } 501 502 IntRect ChromeClientImpl::rootViewToScreen(const IntRect& rect) const 503 { 504 IntRect screenRect(rect); 505 506 if (m_webView->client()) { 507 WebRect windowRect = m_webView->client()->windowRect(); 508 screenRect.move(windowRect.x, windowRect.y); 509 } 510 511 return screenRect; 512 } 513 514 WebScreenInfo ChromeClientImpl::screenInfo() const 515 { 516 return m_webView->client() ? m_webView->client()->screenInfo() : WebScreenInfo(); 517 } 518 519 void ChromeClientImpl::contentsSizeChanged(LocalFrame* frame, const IntSize& size) const 520 { 521 m_webView->didChangeContentsSize(); 522 523 WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(frame); 524 webframe->didChangeContentsSize(size); 525 526 frame->loader().restoreScrollPositionAndViewState(); 527 } 528 529 void ChromeClientImpl::deviceOrPageScaleFactorChanged() const 530 { 531 m_webView->deviceOrPageScaleFactorChanged(); 532 } 533 534 void ChromeClientImpl::layoutUpdated(LocalFrame* frame) const 535 { 536 m_webView->layoutUpdated(WebLocalFrameImpl::fromFrame(frame)); 537 } 538 539 void ChromeClientImpl::mouseDidMoveOverElement( 540 const HitTestResult& result, unsigned modifierFlags) 541 { 542 if (!m_webView->client()) 543 return; 544 545 WebURL url; 546 // Find out if the mouse is over a link, and if so, let our UI know... 547 if (result.isLiveLink() && !result.absoluteLinkURL().string().isEmpty()) { 548 url = result.absoluteLinkURL(); 549 } else if (result.innerNonSharedNode() 550 && (isHTMLObjectElement(*result.innerNonSharedNode()) 551 || isHTMLEmbedElement(*result.innerNonSharedNode()))) { 552 RenderObject* object = result.innerNonSharedNode()->renderer(); 553 if (object && object->isWidget()) { 554 Widget* widget = toRenderWidget(object)->widget(); 555 if (widget && widget->isPluginContainer()) { 556 WebPluginContainerImpl* plugin = toWebPluginContainerImpl(widget); 557 url = plugin->plugin()->linkAtPosition(result.roundedPointInInnerNodeFrame()); 558 } 559 } 560 } 561 562 m_webView->client()->setMouseOverURL(url); 563 } 564 565 void ChromeClientImpl::setToolTip(const String& tooltipText, TextDirection dir) 566 { 567 if (m_webView->client()) 568 m_webView->client()->setToolTipText(tooltipText, toWebTextDirection(dir)); 569 } 570 571 void ChromeClientImpl::dispatchViewportPropertiesDidChange(const ViewportDescription& description) const 572 { 573 m_webView->updatePageDefinedViewportConstraints(description); 574 } 575 576 void ChromeClientImpl::print(LocalFrame* frame) 577 { 578 if (m_webView->client()) 579 m_webView->client()->printPage(WebLocalFrameImpl::fromFrame(frame)); 580 } 581 582 PassOwnPtr<ColorChooser> ChromeClientImpl::createColorChooser(LocalFrame* frame, ColorChooserClient* chooserClient, const Color&) 583 { 584 OwnPtr<ColorChooserUIController> controller; 585 if (RuntimeEnabledFeatures::pagePopupEnabled()) 586 controller = adoptPtr(new ColorChooserPopupUIController(frame, this, chooserClient)); 587 else 588 controller = adoptPtr(new ColorChooserUIController(frame, chooserClient)); 589 controller->openUI(); 590 return controller.release(); 591 } 592 593 PassRefPtr<DateTimeChooser> ChromeClientImpl::openDateTimeChooser(DateTimeChooserClient* pickerClient, const DateTimeChooserParameters& parameters) 594 { 595 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI) 596 return DateTimeChooserImpl::create(this, pickerClient, parameters); 597 #else 598 return ExternalDateTimeChooser::create(this, m_webView->client(), pickerClient, parameters); 599 #endif 600 } 601 602 void ChromeClientImpl::runOpenPanel(LocalFrame* frame, PassRefPtr<FileChooser> fileChooser) 603 { 604 WebViewClient* client = m_webView->client(); 605 if (!client) 606 return; 607 608 WebFileChooserParams params; 609 params.multiSelect = fileChooser->settings().allowsMultipleFiles; 610 params.directory = fileChooser->settings().allowsDirectoryUpload; 611 params.acceptTypes = fileChooser->settings().acceptTypes(); 612 params.selectedFiles = fileChooser->settings().selectedFiles; 613 if (params.selectedFiles.size() > 0) 614 params.initialValue = params.selectedFiles[0]; 615 params.useMediaCapture = fileChooser->settings().useMediaCapture; 616 617 WebFileChooserCompletionImpl* chooserCompletion = 618 new WebFileChooserCompletionImpl(fileChooser); 619 620 if (client->runFileChooser(params, chooserCompletion)) 621 return; 622 623 // Choosing failed, so do callback with an empty list. 624 chooserCompletion->didChooseFile(WebVector<WebString>()); 625 } 626 627 void ChromeClientImpl::enumerateChosenDirectory(FileChooser* fileChooser) 628 { 629 WebViewClient* client = m_webView->client(); 630 if (!client) 631 return; 632 633 WebFileChooserCompletionImpl* chooserCompletion = 634 new WebFileChooserCompletionImpl(fileChooser); 635 636 ASSERT(fileChooser && fileChooser->settings().selectedFiles.size()); 637 638 // If the enumeration can't happen, call the callback with an empty list. 639 if (!client->enumerateChosenDirectory(fileChooser->settings().selectedFiles[0], chooserCompletion)) 640 chooserCompletion->didChooseFile(WebVector<WebString>()); 641 } 642 643 void ChromeClientImpl::setCursor(const Cursor& cursor) 644 { 645 setCursor(WebCursorInfo(cursor)); 646 } 647 648 void ChromeClientImpl::setCursor(const WebCursorInfo& cursor) 649 { 650 #if OS(MACOSX) 651 // On Mac the mousemove event propagates to both the popup and main window. 652 // If a popup is open we don't want the main window to change the cursor. 653 if (m_webView->hasOpenedPopup()) 654 return; 655 #endif 656 if (m_webView->client()) 657 m_webView->client()->didChangeCursor(cursor); 658 } 659 660 void ChromeClientImpl::setCursorForPlugin(const WebCursorInfo& cursor) 661 { 662 setCursor(cursor); 663 } 664 665 void ChromeClientImpl::postAccessibilityNotification(AXObject* obj, AXObjectCache::AXNotification notification) 666 { 667 // Alert assistive technology about the accessibility object notification. 668 if (!obj || !obj->document()) 669 return; 670 671 WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(obj->document()->axObjectCacheOwner().frame()); 672 if (webframe && webframe->client()) 673 webframe->client()->postAccessibilityEvent(WebAXObject(obj), toWebAXEvent(notification)); 674 675 // FIXME: delete these lines once Chrome only uses the frame client interface, above. 676 if (m_webView->client()) 677 m_webView->client()->postAccessibilityEvent(WebAXObject(obj), toWebAXEvent(notification)); 678 } 679 680 String ChromeClientImpl::acceptLanguages() 681 { 682 return m_webView->client()->acceptLanguages(); 683 } 684 685 bool ChromeClientImpl::paintCustomOverhangArea(GraphicsContext* context, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect) 686 { 687 LocalFrame* frame = m_webView->mainFrameImpl()->frame(); 688 WebPluginContainerImpl* pluginContainer = WebLocalFrameImpl::pluginContainerFromFrame(frame); 689 if (pluginContainer) 690 return pluginContainer->paintCustomOverhangArea(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect); 691 return false; 692 } 693 694 GraphicsLayerFactory* ChromeClientImpl::graphicsLayerFactory() const 695 { 696 return m_webView->graphicsLayerFactory(); 697 } 698 699 void ChromeClientImpl::attachRootGraphicsLayer(GraphicsLayer* rootLayer) 700 { 701 m_webView->setRootGraphicsLayer(rootLayer); 702 } 703 704 void ChromeClientImpl::enterFullScreenForElement(Element* element) 705 { 706 m_webView->enterFullScreenForElement(element); 707 } 708 709 void ChromeClientImpl::exitFullScreenForElement(Element* element) 710 { 711 m_webView->exitFullScreenForElement(element); 712 } 713 714 void ChromeClientImpl::clearCompositedSelectionBounds() 715 { 716 m_webView->clearCompositedSelectionBounds(); 717 } 718 719 void ChromeClientImpl::updateCompositedSelectionBounds(const CompositedSelectionBound& anchor, const CompositedSelectionBound& focus) 720 { 721 m_webView->updateCompositedSelectionBounds(toWebSelectionBound(anchor), toWebSelectionBound(focus)); 722 } 723 724 bool ChromeClientImpl::hasOpenedPopup() const 725 { 726 return m_webView->hasOpenedPopup(); 727 } 728 729 PassRefPtrWillBeRawPtr<PopupMenu> ChromeClientImpl::createPopupMenu(LocalFrame& frame, PopupMenuClient* client) const 730 { 731 if (WebViewImpl::useExternalPopupMenus()) 732 return adoptRefWillBeNoop(new ExternalPopupMenu(frame, client, *m_webView)); 733 734 return adoptRefWillBeNoop(new PopupMenuChromium(frame, client)); 735 } 736 737 PagePopup* ChromeClientImpl::openPagePopup(PagePopupClient* client, const IntRect& originBoundsInRootView) 738 { 739 ASSERT(m_pagePopupDriver); 740 return m_pagePopupDriver->openPagePopup(client, originBoundsInRootView); 741 } 742 743 void ChromeClientImpl::closePagePopup(PagePopup* popup) 744 { 745 ASSERT(m_pagePopupDriver); 746 m_pagePopupDriver->closePagePopup(popup); 747 } 748 749 void ChromeClientImpl::setPagePopupDriver(PagePopupDriver* driver) 750 { 751 ASSERT(driver); 752 m_pagePopupDriver = driver; 753 } 754 755 void ChromeClientImpl::resetPagePopupDriver() 756 { 757 m_pagePopupDriver = m_webView; 758 } 759 760 bool ChromeClientImpl::shouldRunModalDialogDuringPageDismissal(const DialogType& dialogType, const String& dialogMessage, Document::PageDismissalType dismissalType) const 761 { 762 const char* kDialogs[] = {"alert", "confirm", "prompt", "showModalDialog"}; 763 int dialog = static_cast<int>(dialogType); 764 ASSERT_WITH_SECURITY_IMPLICATION(0 <= dialog && dialog < static_cast<int>(arraysize(kDialogs))); 765 766 const char* kDismissals[] = {"beforeunload", "pagehide", "unload"}; 767 int dismissal = static_cast<int>(dismissalType) - 1; // Exclude NoDismissal. 768 ASSERT_WITH_SECURITY_IMPLICATION(0 <= dismissal && dismissal < static_cast<int>(arraysize(kDismissals))); 769 770 Platform::current()->histogramEnumeration("Renderer.ModalDialogsDuringPageDismissal", dismissal * arraysize(kDialogs) + dialog, arraysize(kDialogs) * arraysize(kDismissals)); 771 772 String message = String("Blocked ") + kDialogs[dialog] + "('" + dialogMessage + "') during " + kDismissals[dismissal] + "."; 773 m_webView->mainFrame()->addMessageToConsole(WebConsoleMessage(WebConsoleMessage::LevelError, message)); 774 775 return false; 776 } 777 778 void ChromeClientImpl::needTouchEvents(bool needsTouchEvents) 779 { 780 m_webView->hasTouchEventHandlers(needsTouchEvents); 781 } 782 783 void ChromeClientImpl::setTouchAction(TouchAction touchAction) 784 { 785 if (WebViewClient* client = m_webView->client()) { 786 WebTouchAction webTouchAction = static_cast<WebTouchAction>(touchAction); 787 client->setTouchAction(webTouchAction); 788 } 789 } 790 791 bool ChromeClientImpl::requestPointerLock() 792 { 793 return m_webView->requestPointerLock(); 794 } 795 796 void ChromeClientImpl::requestPointerUnlock() 797 { 798 return m_webView->requestPointerUnlock(); 799 } 800 801 void ChromeClientImpl::annotatedRegionsChanged() 802 { 803 WebViewClient* client = m_webView->client(); 804 if (client) 805 client->draggableRegionsChanged(); 806 } 807 808 void ChromeClientImpl::didAssociateFormControls(const WillBeHeapVector<RefPtrWillBeMember<Element> >& elements) 809 { 810 if (m_webView->autofillClient()) 811 m_webView->autofillClient()->didAssociateFormControls(elements); 812 } 813 814 void ChromeClientImpl::didCancelCompositionOnSelectionChange() 815 { 816 if (m_webView->client()) 817 m_webView->client()->didCancelCompositionOnSelectionChange(); 818 } 819 820 void ChromeClientImpl::willSetInputMethodState() 821 { 822 if (m_webView->client()) 823 m_webView->client()->resetInputMethod(); 824 } 825 826 void ChromeClientImpl::didUpdateTextOfFocusedElementByNonUserInput() 827 { 828 if (m_webView->client()) 829 m_webView->client()->didUpdateTextOfFocusedElementByNonUserInput(); 830 } 831 832 void ChromeClientImpl::showImeIfNeeded() 833 { 834 if (m_webView->client()) 835 m_webView->client()->showImeIfNeeded(); 836 } 837 838 void ChromeClientImpl::handleKeyboardEventOnTextField(HTMLInputElement& inputElement, KeyboardEvent& event) 839 { 840 if (!m_webView->autofillClient()) 841 return; 842 m_webView->autofillClient()->textFieldDidReceiveKeyDown(WebInputElement(&inputElement), WebKeyboardEventBuilder(event)); 843 } 844 845 // FIXME: Remove this code once we have input routing in the browser 846 // process. See http://crbug.com/339659. 847 void ChromeClientImpl::forwardInputEvent( 848 Frame* frame, Event* event) 849 { 850 // FIXME: Input event forwarding to out-of-process frames is broken until 851 // WebRemoteFrameImpl has a WebFrameClient. 852 if (frame->isRemoteFrame()) 853 return; 854 855 WebLocalFrameImpl* webFrame = WebLocalFrameImpl::fromFrame(toLocalFrame(frame)); 856 857 // This is only called when we have out-of-process iframes, which 858 // need to forward input events across processes. 859 // FIXME: Add a check for out-of-process iframes enabled. 860 if (event->isKeyboardEvent()) { 861 WebKeyboardEventBuilder webEvent(*static_cast<KeyboardEvent*>(event)); 862 webFrame->client()->forwardInputEvent(&webEvent); 863 } else if (event->isMouseEvent()) { 864 WebMouseEventBuilder webEvent(webFrame->frameView(), frame->ownerRenderer(), *static_cast<MouseEvent*>(event)); 865 // Internal Blink events should not be forwarded. 866 if (webEvent.type == WebInputEvent::Undefined) 867 return; 868 869 webFrame->client()->forwardInputEvent(&webEvent); 870 } else if (event->isWheelEvent()) { 871 WebMouseWheelEventBuilder webEvent(webFrame->frameView(), frame->ownerRenderer(), *static_cast<WheelEvent*>(event)); 872 if (webEvent.type == WebInputEvent::Undefined) 873 return; 874 webFrame->client()->forwardInputEvent(&webEvent); 875 } 876 } 877 878 void ChromeClientImpl::didChangeValueInTextField(HTMLFormControlElement& element) 879 { 880 if (!m_webView->autofillClient()) 881 return; 882 m_webView->autofillClient()->textFieldDidChange(WebFormControlElement(&element)); 883 } 884 885 void ChromeClientImpl::didEndEditingOnTextField(HTMLInputElement& inputElement) 886 { 887 if (m_webView->autofillClient()) 888 m_webView->autofillClient()->textFieldDidEndEditing(WebInputElement(&inputElement)); 889 } 890 891 void ChromeClientImpl::openTextDataListChooser(HTMLInputElement& input) 892 { 893 if (m_webView->autofillClient()) 894 m_webView->autofillClient()->openTextDataListChooser(WebInputElement(&input)); 895 } 896 897 } // namespace blink 898