2 * Copyright (C) 2010, 2011 Apple Inc. All rights reserved.
3 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24 * THE POSSIBILITY OF SUCH DAMAGE.
28 #include "WebChromeClient.h"
30 #include "DrawingArea.h"
31 #include "InjectedBundleNavigationAction.h"
32 #include "InjectedBundleUserMessageCoders.h"
33 #include "WebContextMenu.h"
34 #include "WebCoreArgumentCoders.h"
36 #include "WebFrameLoaderClient.h"
37 #include "WebOpenPanelParameters.h"
38 #include "WebOpenPanelResultListener.h"
40 #include "WebPageCreationParameters.h"
41 #include "WebPageProxyMessages.h"
42 #include "WebPopupMenu.h"
43 #include "WebPreferencesStore.h"
44 #include "WebProcess.h"
45 #include "WebProcessProxyMessageKinds.h"
46 #include "WebSearchPopupMenu.h"
47 #include <WebCore/DatabaseTracker.h>
48 #include <WebCore/FileChooser.h>
49 #include <WebCore/Frame.h>
50 #include <WebCore/FrameLoader.h>
51 #include <WebCore/FrameView.h>
52 #include <WebCore/HTMLNames.h>
53 #include <WebCore/HTMLPlugInImageElement.h>
54 #include <WebCore/NotImplemented.h>
55 #include <WebCore/Page.h>
56 #include <WebCore/SecurityOrigin.h>
58 using namespace WebCore;
59 using namespace HTMLNames;
63 static double area(WebFrame* frame)
65 IntSize size = frame->visibleContentBoundsExcludingScrollbars().size();
66 return static_cast<double>(size.height()) * size.width();
70 static WebFrame* findLargestFrameInFrameSet(WebPage* page)
72 // Approximate what a user could consider a default target frame for application menu operations.
74 WebFrame* mainFrame = page->mainFrame();
75 if (!mainFrame->isFrameSet())
78 WebFrame* largestSoFar = 0;
80 RefPtr<ImmutableArray> frameChildren = mainFrame->childFrames();
81 size_t count = frameChildren->size();
82 for (size_t i = 0; i < count; ++i) {
83 WebFrame* childFrame = frameChildren->at<WebFrame>(i);
84 if (!largestSoFar || area(childFrame) > area(largestSoFar))
85 largestSoFar = childFrame;
91 void WebChromeClient::chromeDestroyed()
96 void WebChromeClient::setWindowRect(const FloatRect& windowFrame)
98 m_page->send(Messages::WebPageProxy::SetWindowFrame(windowFrame));
101 FloatRect WebChromeClient::windowRect()
103 FloatRect newWindowFrame;
105 if (!WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::GetWindowFrame(), Messages::WebPageProxy::GetWindowFrame::Reply(newWindowFrame), m_page->pageID()))
108 return newWindowFrame;
111 FloatRect WebChromeClient::pageRect()
113 return FloatRect(FloatPoint(), m_page->size());
116 float WebChromeClient::scaleFactor()
122 void WebChromeClient::focus()
124 m_page->send(Messages::WebPageProxy::SetFocus(true));
127 void WebChromeClient::unfocus()
129 m_page->send(Messages::WebPageProxy::SetFocus(false));
132 bool WebChromeClient::canTakeFocus(FocusDirection)
138 void WebChromeClient::takeFocus(FocusDirection direction)
140 m_page->send(Messages::WebPageProxy::TakeFocus(direction == FocusDirectionForward ? true : false));
143 void WebChromeClient::focusedNodeChanged(Node*)
148 void WebChromeClient::focusedFrameChanged(Frame* frame)
150 WebFrame* webFrame = frame ? static_cast<WebFrameLoaderClient*>(frame->loader()->client())->webFrame() : 0;
152 WebProcess::shared().connection()->send(Messages::WebPageProxy::FocusedFrameChanged(webFrame ? webFrame->frameID() : 0), m_page->pageID());
155 Page* WebChromeClient::createWindow(Frame*, const FrameLoadRequest&, const WindowFeatures& windowFeatures, const NavigationAction& navigationAction)
157 uint32_t modifiers = static_cast<uint32_t>(InjectedBundleNavigationAction::modifiersForNavigationAction(navigationAction));
158 int32_t mouseButton = static_cast<int32_t>(InjectedBundleNavigationAction::mouseButtonForNavigationAction(navigationAction));
160 uint64_t newPageID = 0;
161 WebPageCreationParameters parameters;
162 if (!WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::CreateNewPage(windowFeatures, modifiers, mouseButton), Messages::WebPageProxy::CreateNewPage::Reply(newPageID, parameters), m_page->pageID()))
168 WebProcess::shared().createWebPage(newPageID, parameters);
169 return WebProcess::shared().webPage(newPageID)->corePage();
172 void WebChromeClient::show()
177 bool WebChromeClient::canRunModal()
179 return m_page->canRunModal();
182 void WebChromeClient::runModal()
187 void WebChromeClient::setToolbarsVisible(bool toolbarsAreVisible)
189 m_page->send(Messages::WebPageProxy::SetToolbarsAreVisible(toolbarsAreVisible));
192 bool WebChromeClient::toolbarsVisible()
194 bool toolbarsAreVisible = true;
195 if (!WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::GetToolbarsAreVisible(), Messages::WebPageProxy::GetToolbarsAreVisible::Reply(toolbarsAreVisible), m_page->pageID()))
198 return toolbarsAreVisible;
201 void WebChromeClient::setStatusbarVisible(bool statusBarIsVisible)
203 m_page->send(Messages::WebPageProxy::SetStatusBarIsVisible(statusBarIsVisible));
206 bool WebChromeClient::statusbarVisible()
208 bool statusBarIsVisible = true;
209 if (!WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::GetStatusBarIsVisible(), Messages::WebPageProxy::GetStatusBarIsVisible::Reply(statusBarIsVisible), m_page->pageID()))
212 return statusBarIsVisible;
215 void WebChromeClient::setScrollbarsVisible(bool)
220 bool WebChromeClient::scrollbarsVisible()
226 void WebChromeClient::setMenubarVisible(bool menuBarVisible)
228 m_page->send(Messages::WebPageProxy::SetMenuBarIsVisible(menuBarVisible));
231 bool WebChromeClient::menubarVisible()
233 bool menuBarIsVisible = true;
234 if (!WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::GetMenuBarIsVisible(), Messages::WebPageProxy::GetMenuBarIsVisible::Reply(menuBarIsVisible), m_page->pageID()))
237 return menuBarIsVisible;
240 void WebChromeClient::setResizable(bool resizable)
242 m_page->send(Messages::WebPageProxy::SetIsResizable(resizable));
245 void WebChromeClient::addMessageToConsole(MessageSource, MessageType, MessageLevel, const String& message, unsigned int lineNumber, const String& sourceID)
247 // Notify the bundle client.
248 m_page->injectedBundleUIClient().willAddMessageToConsole(m_page, message, lineNumber);
253 bool WebChromeClient::canRunBeforeUnloadConfirmPanel()
255 return m_page->canRunBeforeUnloadConfirmPanel();
258 bool WebChromeClient::runBeforeUnloadConfirmPanel(const String& message, Frame* frame)
260 WebFrame* webFrame = static_cast<WebFrameLoaderClient*>(frame->loader()->client())->webFrame();
262 bool shouldClose = false;
263 if (!WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::RunBeforeUnloadConfirmPanel(message, webFrame->frameID()), Messages::WebPageProxy::RunBeforeUnloadConfirmPanel::Reply(shouldClose), m_page->pageID()))
269 void WebChromeClient::closeWindowSoon()
271 // FIXME: This code assumes that the client will respond to a close page
272 // message by actually closing the page. Safari does this, but there is
273 // no guarantee that other applications will, which will leave this page
274 // half detached. This approach is an inherent limitation making parts of
275 // a close execute synchronously as part of window.close, but other parts
278 m_page->corePage()->setGroupName(String());
280 if (WebFrame* frame = m_page->mainFrame()) {
281 if (Frame* coreFrame = frame->coreFrame())
282 coreFrame->loader()->stopForUserCancel();
288 void WebChromeClient::runJavaScriptAlert(Frame* frame, const String& alertText)
290 WebFrame* webFrame = static_cast<WebFrameLoaderClient*>(frame->loader()->client())->webFrame();
292 // Notify the bundle client.
293 m_page->injectedBundleUIClient().willRunJavaScriptAlert(m_page, alertText, webFrame);
295 WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::RunJavaScriptAlert(webFrame->frameID(), alertText), Messages::WebPageProxy::RunJavaScriptAlert::Reply(), m_page->pageID());
298 bool WebChromeClient::runJavaScriptConfirm(Frame* frame, const String& message)
300 WebFrame* webFrame = static_cast<WebFrameLoaderClient*>(frame->loader()->client())->webFrame();
302 // Notify the bundle client.
303 m_page->injectedBundleUIClient().willRunJavaScriptConfirm(m_page, message, webFrame);
306 if (!WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::RunJavaScriptConfirm(webFrame->frameID(), message), Messages::WebPageProxy::RunJavaScriptConfirm::Reply(result), m_page->pageID()))
312 bool WebChromeClient::runJavaScriptPrompt(Frame* frame, const String& message, const String& defaultValue, String& result)
314 WebFrame* webFrame = static_cast<WebFrameLoaderClient*>(frame->loader()->client())->webFrame();
316 // Notify the bundle client.
317 m_page->injectedBundleUIClient().willRunJavaScriptPrompt(m_page, message, defaultValue, webFrame);
319 if (!WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::RunJavaScriptPrompt(webFrame->frameID(), message, defaultValue), Messages::WebPageProxy::RunJavaScriptPrompt::Reply(result), m_page->pageID()))
322 return !result.isNull();
325 void WebChromeClient::setStatusbarText(const String& statusbarText)
327 // Notify the bundle client.
328 m_page->injectedBundleUIClient().willSetStatusbarText(m_page, statusbarText);
330 m_page->send(Messages::WebPageProxy::SetStatusText(statusbarText));
333 bool WebChromeClient::shouldInterruptJavaScript()
339 KeyboardUIMode WebChromeClient::keyboardUIMode()
341 return m_page->keyboardUIMode();
344 IntRect WebChromeClient::windowResizerRect() const
346 return m_page->windowResizerRect();
349 void WebChromeClient::invalidateWindow(const IntRect&, bool)
351 // Do nothing here, there's no concept of invalidating the window in the web process.
354 void WebChromeClient::invalidateContentsAndWindow(const IntRect& rect, bool)
356 if (m_page->corePage()->mainFrame()->document()->printing())
358 m_page->drawingArea()->setNeedsDisplay(rect);
361 void WebChromeClient::invalidateContentsForSlowScroll(const IntRect& rect, bool)
363 if (m_page->corePage()->mainFrame()->document()->printing())
365 m_page->pageDidScroll();
366 m_page->drawingArea()->setNeedsDisplay(rect);
369 void WebChromeClient::scroll(const IntSize& scrollOffset, const IntRect& scrollRect, const IntRect& clipRect)
371 m_page->pageDidScroll();
372 m_page->drawingArea()->scroll(intersection(scrollRect, clipRect), scrollOffset);
375 #if ENABLE(TILED_BACKING_STORE)
376 void WebChromeClient::delegatedScrollRequested(const IntSize& scrollOffset)
378 m_page->pageDidRequestScroll(scrollOffset);
382 IntPoint WebChromeClient::screenToWindow(const IntPoint&) const
388 IntRect WebChromeClient::windowToScreen(const IntRect& rect) const
390 return m_page->windowToScreen(rect);
393 PlatformPageClient WebChromeClient::platformPageClient() const
399 void WebChromeClient::contentsSizeChanged(Frame* frame, const IntSize& size) const
402 #if ENABLE(TILED_BACKING_STORE)
403 if (frame->page()->mainFrame() == frame)
404 m_page->resizeToContentsIfNeeded();
407 WebFrame* webFrame = static_cast<WebFrameLoaderClient*>(frame->loader()->client())->webFrame();
409 if (!m_page->mainFrame() || m_page->mainFrame() != webFrame)
412 m_page->send(Messages::WebPageProxy::DidChangeContentsSize(size));
415 WebFrame* largestFrame = findLargestFrameInFrameSet(m_page);
416 if (largestFrame != m_cachedFrameSetLargestFrame.get()) {
417 m_cachedFrameSetLargestFrame = largestFrame;
418 m_page->send(Messages::WebPageProxy::FrameSetLargestFrameChanged(largestFrame ? largestFrame->frameID() : 0));
421 if (frame->page()->mainFrame() != frame)
423 FrameView* frameView = frame->view();
427 bool hasHorizontalScrollbar = frameView->horizontalScrollbar();
428 bool hasVerticalScrollbar = frameView->verticalScrollbar();
430 if (hasHorizontalScrollbar != m_cachedMainFrameHasHorizontalScrollbar || hasVerticalScrollbar != m_cachedMainFrameHasVerticalScrollbar) {
431 m_page->send(Messages::WebPageProxy::DidChangeScrollbarsForMainFrame(hasHorizontalScrollbar, hasVerticalScrollbar));
433 m_cachedMainFrameHasHorizontalScrollbar = hasHorizontalScrollbar;
434 m_cachedMainFrameHasVerticalScrollbar = hasVerticalScrollbar;
438 void WebChromeClient::scrollRectIntoView(const IntRect&, const ScrollView*) const
443 bool WebChromeClient::shouldMissingPluginMessageBeButton() const
445 // FIXME: <rdar://problem/8794397> We should only return true when there is a
446 // missingPluginButtonClicked callback defined on the Page UI client.
450 void WebChromeClient::missingPluginButtonClicked(Element* element) const
452 ASSERT(element->hasTagName(objectTag) || element->hasTagName(embedTag));
454 HTMLPlugInImageElement* pluginElement = static_cast<HTMLPlugInImageElement*>(element);
456 m_page->send(Messages::WebPageProxy::MissingPluginButtonClicked(pluginElement->serviceType(), pluginElement->url(), pluginElement->getAttribute(pluginspageAttr)));
459 void WebChromeClient::scrollbarsModeDidChange() const
464 void WebChromeClient::mouseDidMoveOverElement(const HitTestResult& hitTestResult, unsigned modifierFlags)
466 RefPtr<APIObject> userData;
468 // Notify the bundle client.
469 m_page->injectedBundleUIClient().mouseDidMoveOverElement(m_page, hitTestResult, static_cast<WebEvent::Modifiers>(modifierFlags), userData);
471 // Notify the UIProcess.
472 m_page->send(Messages::WebPageProxy::MouseDidMoveOverElement(modifierFlags, InjectedBundleUserMessageEncoder(userData.get())));
475 void WebChromeClient::setToolTip(const String& toolTip, TextDirection)
477 // Only send a tool tip to the WebProcess if it has changed since the last time this function was called.
479 if (toolTip == m_cachedToolTip)
481 m_cachedToolTip = toolTip;
483 m_page->send(Messages::WebPageProxy::SetToolTip(m_cachedToolTip));
486 void WebChromeClient::print(Frame* frame)
488 WebFrame* webFrame = static_cast<WebFrameLoaderClient*>(frame->loader()->client())->webFrame();
489 m_page->sendSync(Messages::WebPageProxy::PrintFrame(webFrame->frameID()), Messages::WebPageProxy::PrintFrame::Reply());
493 void WebChromeClient::exceededDatabaseQuota(Frame* frame, const String& databaseName)
495 WebFrame* webFrame = static_cast<WebFrameLoaderClient*>(frame->loader()->client())->webFrame();
496 SecurityOrigin* origin = frame->document()->securityOrigin();
498 DatabaseDetails details = DatabaseTracker::tracker().detailsForNameAndOrigin(databaseName, origin);
499 uint64_t currentQuota = DatabaseTracker::tracker().quotaForOrigin(origin);
500 uint64_t newQuota = 0;
501 WebProcess::shared().connection()->sendSync(
502 Messages::WebPageProxy::ExceededDatabaseQuota(webFrame->frameID(), origin->databaseIdentifier(), databaseName, details.displayName(), currentQuota, details.currentUsage(), details.expectedUsage()),
503 Messages::WebPageProxy::ExceededDatabaseQuota::Reply(newQuota), m_page->pageID());
505 DatabaseTracker::tracker().setQuota(origin, newQuota);
510 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
511 void WebChromeClient::reachedMaxAppCacheSize(int64_t)
516 void WebChromeClient::reachedApplicationCacheOriginQuota(SecurityOrigin*)
522 #if ENABLE(DASHBOARD_SUPPORT)
523 void WebChromeClient::dashboardRegionsChanged()
529 void WebChromeClient::populateVisitedLinks()
533 FloatRect WebChromeClient::customHighlightRect(Node*, const AtomicString& type, const FloatRect& lineRect)
539 void WebChromeClient::paintCustomHighlight(Node*, const AtomicString& type, const FloatRect& boxRect, const FloatRect& lineRect,
540 bool behindText, bool entireLine)
545 bool WebChromeClient::shouldReplaceWithGeneratedFileForUpload(const String& path, String& generatedFilename)
551 String WebChromeClient::generateReplacementFile(const String& path)
557 bool WebChromeClient::paintCustomScrollbar(GraphicsContext*, const FloatRect&, ScrollbarControlSize,
558 ScrollbarControlState, ScrollbarPart pressedPart, bool vertical,
559 float value, float proportion, ScrollbarControlPartMask)
565 bool WebChromeClient::paintCustomScrollCorner(GraphicsContext*, const FloatRect&)
571 bool WebChromeClient::paintCustomOverhangArea(GraphicsContext* context, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect)
573 if (!m_page->injectedBundleUIClient().shouldPaintCustomOverhangArea())
576 m_page->injectedBundleUIClient().paintCustomOverhangArea(m_page, context, horizontalOverhangArea, verticalOverhangArea, dirtyRect);
580 void WebChromeClient::requestGeolocationPermissionForFrame(Frame*, Geolocation*)
585 void WebChromeClient::cancelGeolocationPermissionRequestForFrame(Frame*, Geolocation*)
590 void WebChromeClient::runOpenPanel(Frame* frame, PassRefPtr<FileChooser> prpFileChooser)
592 if (m_page->activeOpenPanelResultListener())
595 RefPtr<FileChooser> fileChooser = prpFileChooser;
597 m_page->setActiveOpenPanelResultListener(WebOpenPanelResultListener::create(m_page, fileChooser.get()));
599 WebOpenPanelParameters::Data parameters;
600 parameters.allowMultipleFiles = fileChooser->allowsMultipleFiles();
601 #if ENABLE(DIRECTORY_UPLOAD)
602 parameters.allowsDirectoryUpload = fileChooser->allowsDirectoryUpload();
604 parameters.allowsDirectoryUpload = false;
606 parameters.acceptTypes = fileChooser->acceptTypes();
607 parameters.filenames = fileChooser->filenames();
609 m_page->send(Messages::WebPageProxy::RunOpenPanel(static_cast<WebFrameLoaderClient*>(frame->loader()->client())->webFrame()->frameID(), parameters));
612 void WebChromeClient::chooseIconForFiles(const Vector<String>&, FileChooser*)
617 void WebChromeClient::setCursor(const WebCore::Cursor& cursor)
619 #if USE(LAZY_NATIVE_CURSOR)
620 m_page->send(Messages::WebPageProxy::SetCursor(cursor));
624 void WebChromeClient::formStateDidChange(const Node*)
629 void WebChromeClient::formDidFocus(const Node*)
634 void WebChromeClient::formDidBlur(const Node*)
639 bool WebChromeClient::selectItemWritingDirectionIsNatural()
644 bool WebChromeClient::selectItemAlignmentFollowsMenuWritingDirection()
649 PassRefPtr<WebCore::PopupMenu> WebChromeClient::createPopupMenu(WebCore::PopupMenuClient* client) const
651 return WebPopupMenu::create(m_page, client);
654 PassRefPtr<WebCore::SearchPopupMenu> WebChromeClient::createSearchPopupMenu(WebCore::PopupMenuClient* client) const
656 return WebSearchPopupMenu::create(m_page, client);
659 #if ENABLE(CONTEXT_MENUS)
660 void WebChromeClient::showContextMenu()
662 m_page->contextMenu()->show();
666 #if USE(ACCELERATED_COMPOSITING)
667 void WebChromeClient::attachRootGraphicsLayer(Frame*, GraphicsLayer* layer)
670 m_page->enterAcceleratedCompositingMode(layer);
672 m_page->exitAcceleratedCompositingMode();
675 void WebChromeClient::setNeedsOneShotDrawingSynchronization()
680 void WebChromeClient::scheduleCompositingLayerSync()
682 if (m_page->drawingArea())
683 m_page->drawingArea()->scheduleCompositingLayerSync();
688 #if ENABLE(NOTIFICATIONS)
689 WebCore::NotificationPresenter* WebChromeClient::notificationPresenter() const
695 #if ENABLE(TOUCH_EVENTS)
696 void WebChromeClient::needTouchEvents(bool)
702 void WebChromeClient::setLastSetCursorToCurrentCursor()
707 void WebChromeClient::dispatchViewportDataDidChange(const ViewportArguments& args) const
709 m_page->send(Messages::WebPageProxy::DidChangeViewportData(args));
712 void WebChromeClient::didCompleteRubberBandForMainFrame(const IntSize& initialOverhang) const
714 m_page->send(Messages::WebPageProxy::DidCompleteRubberBandForMainFrame(initialOverhang));
717 } // namespace WebKit