2 * Copyright (C) 2006 Zack Rusin <zack@kde.org>
3 * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
4 * Copyright (C) 2008 Kenneth Rohde Christiansen
5 * Copyright (C) 2008 Diego Gonzalez
6 * Copyright (C) 2009-2010 ProFUSION embedded systems
7 * Copyright (C) 2009-2010 Samsung Electronics
8 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
10 * All rights reserved.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
21 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
29 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include "ChromeClientEfl.h"
37 #if ENABLE(SQL_DATABASE)
39 #include "DatabaseDetails.h"
40 #include "DatabaseTracker.h"
43 #include "FileChooser.h"
44 #include "FileIconLoader.h"
45 #include "FloatRect.h"
46 #include "FrameLoader.h"
47 #include "FrameLoaderClientEfl.h"
48 #include "HitTestResult.h"
51 #include "NavigationAction.h"
52 #if ENABLE(NOTIFICATIONS)
53 #include "NotificationPresenterClientEfl.h"
55 #include "NotImplemented.h"
56 #include "PlatformString.h"
57 #include "PopupMenuEfl.h"
58 #include "SearchPopupMenuEfl.h"
59 #include "SecurityOrigin.h"
60 #include "ViewportArguments.h"
61 #include "WindowFeatures.h"
62 #include "ewk_private.h"
63 #include <Ecore_Evas.h>
65 #include <wtf/text/CString.h>
67 #if ENABLE(TIZEN_MEDIA_QUERY)
71 #if ENABLE(TIZEN_GEOLOCATION)
72 #include "Geolocation.h"
74 ewk_geolocation_permission_dialog_show_callback g_geolocation_permission_dialog_show_callback = 0;
77 using namespace WebCore;
79 static inline Evas_Object* kit(Frame* frame)
84 FrameLoaderClientEfl* client = static_cast<FrameLoaderClientEfl*>(frame->loader()->client());
85 return client ? client->webFrame() : 0;
90 ChromeClientEfl::ChromeClientEfl(Evas_Object* view)
96 ChromeClientEfl::~ChromeClientEfl()
100 void ChromeClientEfl::chromeDestroyed()
105 void ChromeClientEfl::focusedNodeChanged(Node*)
110 void ChromeClientEfl::focusedFrameChanged(Frame*)
114 FloatRect ChromeClientEfl::windowRect()
119 ee = ecore_evas_ecore_evas_get(evas_object_evas_get(m_view));
120 ecore_evas_geometry_get(ee, &x, &y, &w, &h);
121 return FloatRect(x, y, w, h);
124 void ChromeClientEfl::setWindowRect(const FloatRect& rect)
126 if (!ewk_view_setting_enable_auto_resize_window_get(m_view))
130 IntRect intrect = IntRect(rect);
132 ee = ecore_evas_ecore_evas_get(evas_object_evas_get(m_view));
133 ecore_evas_move(ee, intrect.x(), intrect.y());
134 ecore_evas_resize(ee, intrect.width(), intrect.height());
137 FloatRect ChromeClientEfl::pageRect()
139 return ewk_view_page_rect_get(m_view);
142 #if ENABLE(TIZEN_INNER_SCREEN_RECT)
143 FloatRect ChromeClientEfl::innerScreenRect()
146 evas_object_geometry_get(m_view, &x, &y, &w, &h);
147 return FloatRect(x, y, w, h);
151 #if ENABLE(TIZEN_MEDIA_QUERY)
152 int ChromeClientEfl::getDPI()
154 return ecore_x_dpi_get();
157 double ChromeClientEfl::getDPCM()
159 // dpi : dots per inch, dpcm : dots per centimeter
161 // So, dpcm = dpi / 2.54
162 int dpi = ecore_x_dpi_get();
163 double dpcm = dpi / 2.54;
169 void ChromeClientEfl::focus()
171 evas_object_focus_set(m_view, EINA_TRUE);
174 void ChromeClientEfl::unfocus()
176 evas_object_focus_set(m_view, EINA_FALSE);
179 #if ENABLE(TIZEN_FORM_SUBMIT_SUPPORT)
180 Page* ChromeClientEfl::createWindow(Frame* frame, const FrameLoadRequest& frameLoadRequest, const WindowFeatures& features, const NavigationAction& action)
182 Page* ChromeClientEfl::createWindow(Frame*, const FrameLoadRequest& frameLoadRequest, const WindowFeatures& features, const NavigationAction&)
185 #if ENABLE(TIZEN_FORM_SUBMIT_SUPPORT)
186 // When new window is created by website's javascript, some target pages doesn't have any signs related to mobile.
187 // So, our browser doesn't show the patch as mobile page. In order to fix this problem, additional parameter is added to window creation
188 // function. - Gyuyoung Kim.
189 Eina_Bool isMobile = EINA_FALSE;
190 String url = frameLoadRequest.resourceRequest().url().string();
191 if (url.startsWith("http://www.facebook.com/connect"))
192 isMobile = EINA_TRUE;
194 Evas_Object* newView = ewk_view_window_create(m_view, frame, EINA_TRUE, isMobile, &features, action, frameLoadRequest.frameName());
196 Evas_Object* newView = ewk_view_window_create(m_view, frame, EINA_TRUE, &features);
201 return ewk_view_core_page_get(newView);
204 void ChromeClientEfl::show()
206 ewk_view_ready(m_view);
209 bool ChromeClientEfl::canRunModal()
215 void ChromeClientEfl::runModal()
220 void ChromeClientEfl::setToolbarsVisible(bool visible)
222 ewk_view_toolbars_visible_set(m_view, visible);
225 bool ChromeClientEfl::toolbarsVisible()
229 ewk_view_toolbars_visible_get(m_view, &visible);
233 void ChromeClientEfl::setStatusbarVisible(bool visible)
235 ewk_view_statusbar_visible_set(m_view, visible);
238 bool ChromeClientEfl::statusbarVisible()
242 ewk_view_statusbar_visible_get(m_view, &visible);
246 void ChromeClientEfl::setScrollbarsVisible(bool visible)
248 ewk_view_scrollbars_visible_set(m_view, visible);
251 bool ChromeClientEfl::scrollbarsVisible()
255 ewk_view_scrollbars_visible_get(m_view, &visible);
259 void ChromeClientEfl::setMenubarVisible(bool visible)
261 ewk_view_menubar_visible_set(m_view, visible);
264 bool ChromeClientEfl::menubarVisible()
268 ewk_view_menubar_visible_get(m_view, &visible);
272 void ChromeClientEfl::createSelectPopup(PopupMenuClient* client, int selected, const IntRect& rect)
274 ewk_view_popup_new(m_view, client, selected, rect);
277 bool ChromeClientEfl::destroySelectPopup()
279 return ewk_view_popup_destroy(m_view);
282 void ChromeClientEfl::setResizable(bool)
287 void ChromeClientEfl::closeWindowSoon()
289 ewk_view_window_close(m_view);
292 bool ChromeClientEfl::canTakeFocus(FocusDirection coreDirection)
294 // This is called when cycling through links/focusable objects and we
295 // reach the last focusable object.
296 ASSERT(coreDirection == FocusDirectionForward || coreDirection == FocusDirectionBackward);
298 Ewk_Focus_Direction direction = static_cast<Ewk_Focus_Direction>(coreDirection);
300 return !ewk_view_focus_can_cycle(m_view, direction);
303 void ChromeClientEfl::takeFocus(FocusDirection)
308 bool ChromeClientEfl::canRunBeforeUnloadConfirmPanel()
313 bool ChromeClientEfl::runBeforeUnloadConfirmPanel(const String& message, Frame* frame)
315 return runJavaScriptConfirm(frame, message);
318 void ChromeClientEfl::addMessageToConsole(MessageSource, MessageType, MessageLevel, const String& message,
319 unsigned int lineNumber, const String& sourceID)
321 ewk_view_add_console_message(m_view, message.utf8().data(), lineNumber, sourceID.utf8().data());
324 void ChromeClientEfl::runJavaScriptAlert(Frame* frame, const String& message)
326 ewk_view_run_javascript_alert(m_view, kit(frame), message.utf8().data());
329 bool ChromeClientEfl::runJavaScriptConfirm(Frame* frame, const String& message)
331 return ewk_view_run_javascript_confirm(m_view, kit(frame), message.utf8().data());
334 bool ChromeClientEfl::runJavaScriptPrompt(Frame* frame, const String& message, const String& defaultValue, String& result)
337 ewk_view_run_javascript_prompt(m_view, kit(frame), message.utf8().data(), defaultValue.utf8().data(), &value);
339 result = String::fromUTF8(value);
346 void ChromeClientEfl::setStatusbarText(const String& string)
348 ewk_view_statusbar_text_set(m_view, string.utf8().data());
351 bool ChromeClientEfl::shouldInterruptJavaScript()
353 return ewk_view_should_interrupt_javascript(m_view);
356 KeyboardUIMode ChromeClientEfl::keyboardUIMode()
358 return KeyboardAccessTabsToLinks;
361 IntRect ChromeClientEfl::windowResizerRect() const
364 // Implementing this function will make repaint being
365 // called during resize, but as this will be done with
366 // a minor delay it adds a weird "filling" effect due
367 // to us using an evas image for showing the cairo
368 // context. So instead of implementing this function
369 // we call paint directly during resize with
370 // the new object size as its argument.
374 #if ENABLE(TIZEN_SUPPORT_WEBAPP_META_TAG)
375 void ChromeClientEfl::setMobileWebAppCapableState(const String& content)
377 if (equalIgnoringCase(content, "yes"))
378 ewk_view_mobile_web_app_capable_state_set(m_view, content.utf8().data());
381 void ChromeClientEfl::setMobileWebAppStatusBarStyle(const String& content)
383 if (equalIgnoringCase(content, "default")
384 || equalIgnoringCase(content, "black")
385 || equalIgnoringCase(content, "black-translucent"))
386 ewk_view_mobile_web_app_status_bar_style_set(m_view, content.utf8().data());
390 #if ENABLE(TIZEN_SUPPORT_VIEWPORT)
391 bool ChromeClientEfl::canContentsSizeChange(Frame* frame, const IntSize& size) const
393 if (ewk_view_frame_main_get(m_view) == kit(frame))
394 return ewk_view_contents_size_change_possible(m_view, size.width(), size.height());
400 void ChromeClientEfl::contentsSizeChanged(Frame* frame, const IntSize& size) const
402 ewk_frame_contents_size_changed(kit(frame), size.width(), size.height());
403 if (ewk_view_frame_main_get(m_view) == kit(frame))
404 ewk_view_contents_size_changed(m_view, size.width(), size.height());
407 IntRect ChromeClientEfl::rootViewToScreen(const IntRect& rect) const
409 #if ENABLE(TIZEN_SUPPORT_PLUGINS) && ENABLE(TIZEN_CAIRO_SCALE_PATCH)
410 // mariusz.g@samsung.com
411 IntRect result(rect);
412 float zoomRatio = ewk_view_zoom_get(m_view);
413 result.setX((int)(zoomRatio * rect.x()));
414 result.setY((int)(zoomRatio * rect.y()));
415 result.setWidth((int)(zoomRatio * rect.width()));
416 result.setHeight((int)(zoomRatio * rect.height()));
424 IntPoint ChromeClientEfl::screenToRootView(const IntPoint& point) const
430 PlatformPageClient ChromeClientEfl::platformPageClient() const
435 void ChromeClientEfl::scrollbarsModeDidChange() const
439 void ChromeClientEfl::mouseDidMoveOverElement(const HitTestResult& hit, unsigned modifierFlags)
441 // FIXME, compare with old link, look at Qt impl.
442 bool isLink = hit.isLiveLink();
444 KURL url = hit.absoluteLinkURL();
445 if (!url.isEmpty() && url != m_hoveredLinkURL) {
448 CString urlStr = url.string().utf8();
449 CString titleStr = hit.title(dir).utf8();
450 link[0] = urlStr.data();
451 link[1] = titleStr.data();
452 ewk_view_mouse_link_hover_in(m_view, link);
453 m_hoveredLinkURL = url;
455 } else if (!isLink && !m_hoveredLinkURL.isEmpty()) {
456 ewk_view_mouse_link_hover_out(m_view);
457 m_hoveredLinkURL = KURL();
461 void ChromeClientEfl::setToolTip(const String& toolTip, TextDirection)
463 ewk_view_tooltip_text_set(m_view, toolTip.utf8().data());
466 void ChromeClientEfl::print(Frame* frame)
471 void ChromeClientEfl::reachedMaxAppCacheSize(int64_t spaceNeeded)
473 // FIXME: Free some space.
477 void ChromeClientEfl::reachedApplicationCacheOriginQuota(SecurityOrigin*, int64_t)
482 #if ENABLE(TOUCH_EVENTS)
483 void ChromeClientEfl::needTouchEvents(bool needed)
485 ewk_view_need_touch_events_set(m_view, needed);
489 #if ENABLE(TIZEN_EVAS_OBJECT_PLUGIN)
490 void ChromeClientEfl::getPluginStorage(PluginStorage* pluginStorage)
492 ewk_view_get_plugin_storage(m_view , pluginStorage);
494 #if ENABLE(TIZEN_SUPPORT_PLUGINS) && ENABLE(TIZEN_DONT_PAN_OVER_SOME_PLUGINS)
495 void ChromeClientEfl::repeatEventsToPlugin(bool enabled)
497 ewk_view_events_repeat_to_plugin(m_view, enabled);
500 void ChromeClientEfl::eventsHandledByPluginChanged(bool newState)
502 ewk_view_events_handled_by_plugin_changed(m_view, newState);
507 #if ENABLE(SQL_DATABASE)
508 void ChromeClientEfl::exceededDatabaseQuota(Frame* frame, const String& databaseName)
511 SecurityOrigin* origin = frame->document()->securityOrigin();
513 DatabaseDetails details = DatabaseTracker::tracker().detailsForNameAndOrigin(databaseName, origin);
514 quota = ewk_view_exceeded_database_quota(m_view,
515 kit(frame), databaseName.utf8().data(),
516 details.currentUsage(), details.expectedUsage());
518 /* if client did not set quota, and database is being created now, the
519 * default quota is applied
521 if (!quota && !DatabaseTracker::tracker().hasEntryForOrigin(origin))
522 quota = ewk_settings_web_database_default_quota_get();
524 DatabaseTracker::tracker().setQuota(origin, quota);
528 #if ENABLE(NOTIFICATIONS)
529 NotificationPresenter* ChromeClientEfl::notificationPresenter() const
531 #if ENABLE(TIZEN_NOTIFICATION)
532 return ewk_view_notification_presenter_get(m_view);
539 void ChromeClientEfl::runOpenPanel(Frame* frame, PassRefPtr<FileChooser> prpFileChooser)
541 RefPtr<FileChooser> chooser = prpFileChooser;
542 Eina_List* selectedFilenames = 0;
544 Vector<String> filenames;
546 const FileChooserSettings& settings = chooser->settings();
547 bool confirm = ewk_view_run_open_panel(m_view, kit(frame), settings.allowsMultipleFiles, settings.acceptMIMETypes, &selectedFilenames);
552 EINA_LIST_FREE(selectedFilenames, filename) {
553 filenames.append((char*)filename);
557 if (chooser->settings().allowsMultipleFiles)
558 chooser->chooseFiles(filenames);
560 chooser->chooseFile(filenames[0]);
563 void ChromeClientEfl::formStateDidChange(const Node*)
568 void ChromeClientEfl::setCursor(const Cursor&)
573 void ChromeClientEfl::setCursorHiddenUntilMouseMoves(bool)
578 #if ENABLE(TIZEN_GEOLOCATION)
579 void ChromeClientEfl::requestGeolocationPermissionForFrame(Frame* frame, Geolocation* geolocation)
581 // See the comment in WebCore/page/ChromeClient.h
582 if (g_geolocation_permission_dialog_show_callback) {
583 g_geolocation_permission_dialog_show_callback(
585 frame->document()->url().host().latin1().data()
589 evas_object_smart_callback_call(m_view, "geolocation,request", kit(frame));
592 void ChromeClientEfl::requestGeolocationPermissionForFrame(Frame*, Geolocation*)
594 // See the comment in WebCore/page/ChromeClient.h
599 #if ENABLE(TIZEN_GEOLOCATION)
600 void ChromeClientEfl::cancelGeolocationPermissionRequestForFrame(Frame* frame, Geolocation*)
602 void ChromeClientEfl::cancelGeolocationPermissionRequestForFrame(Frame*, Geolocation*)
605 #if ENABLE(TIZEN_GEOLOCATION)
606 evas_object_smart_callback_call(m_view, "geolocation,request,cancel", kit(frame));
612 void ChromeClientEfl::cancelGeolocationPermissionForFrame(Frame*, Geolocation*)
617 void ChromeClientEfl::invalidateContents(const IntRect& updateRect, bool immediate)
622 void ChromeClientEfl::invalidateRootView(const IntRect& updateRect, bool immediate)
627 void ChromeClientEfl::invalidateContentsAndRootView(const IntRect& updateRect, bool immediate)
629 if (updateRect.isEmpty())
632 Evas_Coord x, y, w, h;
636 w = updateRect.width();
637 h = updateRect.height();
639 ewk_view_repaint(m_view, x, y, w, h);
642 void ChromeClientEfl::invalidateContentsForSlowScroll(const IntRect& updateRect, bool immediate)
644 #if ENABLE(TIZEN_OFFSET_UPDATE)
645 ewk_view_tiled_offset_update(m_view);
647 invalidateContentsAndRootView(updateRect, immediate);
650 void ChromeClientEfl::scroll(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
652 ewk_view_scroll(m_view, scrollDelta.width(), scrollDelta.height(), rectToScroll.x(), rectToScroll.y(), rectToScroll.width(), rectToScroll.height(), clipRect.x(), clipRect.y(), clipRect.width(), clipRect.height(), EINA_TRUE);
655 void ChromeClientEfl::cancelGeolocationPermissionRequestForFrame(Frame*)
660 void ChromeClientEfl::iconForFiles(const Vector<String, 0u>&, PassRefPtr<FileChooser>)
665 void ChromeClientEfl::loadIconForFiles(const Vector<String>&, FileIconLoader*)
670 void ChromeClientEfl::dispatchViewportPropertiesDidChange(const ViewportArguments& arguments) const
672 ewk_view_viewport_attributes_set(m_view, arguments);
675 bool ChromeClientEfl::selectItemWritingDirectionIsNatural()
680 bool ChromeClientEfl::selectItemAlignmentFollowsMenuWritingDirection()
685 PassRefPtr<PopupMenu> ChromeClientEfl::createPopupMenu(PopupMenuClient* client) const
687 return adoptRef(new PopupMenuEfl(client));
690 PassRefPtr<SearchPopupMenu> ChromeClientEfl::createSearchPopupMenu(PopupMenuClient* client) const
692 return adoptRef(new SearchPopupMenuEfl(client));
695 #if USE(ACCELERATED_COMPOSITING)
696 void ChromeClientEfl::attachRootGraphicsLayer(Frame* frame, GraphicsLayer* graphicsLayer)
698 #if ENABLE(TIZEN_ACCELERATED_COMPOSITING)
700 ewk_view_root_graphics_layer_set(m_view, graphicsLayer);
701 #endif // ENABLE(TIZEN_ACCELERATED_COMPOSITING)
704 void ChromeClientEfl::setNeedsOneShotDrawingSynchronization()
706 #if ENABLE(TIZEN_ACCELERATED_COMPOSITING)
711 void ChromeClientEfl::scheduleCompositingLayerSync()
713 #if ENABLE(TIZEN_ACCELERATED_COMPOSITING)
715 ewk_view_mark_for_sync(m_view, false);
716 #endif // ENABLE(TIZEN_ACCELERATED_COMPOSITING)
719 bool ChromeClientEfl::allowsAcceleratedCompositing() const
721 #if ENABLE(TIZEN_ACCELERATED_COMPOSITING)
722 Settings* settings = ewk_view_core_page_get(m_view)->settings();
723 return settings->acceleratedCompositingEnabled();
727 ChromeClient::CompositingTriggerFlags ChromeClientEfl::allowedCompositingTriggers() const
729 #if ENABLE(TIZEN_ACCELERATED_COMPOSITING)
730 CompositingTriggerFlags flags = 0;
731 Settings* settings = ewk_view_core_page_get(m_view)->settings();
733 if (settings->acceleratedCompositingFor3DTransformsEnabled())
734 flags |= ThreeDTransformTrigger;
736 if (settings->acceleratedCompositingForVideoEnabled())
737 flags |= VideoTrigger;
739 if (settings->acceleratedCompositingForPluginsEnabled())
740 flags |= PluginTrigger;
742 if (settings->acceleratedCompositingForAnimationEnabled())
743 flags |= AnimationTrigger;
745 if (settings->acceleratedCompositingForCanvasEnabled())
746 flags |= CanvasTrigger;
752 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
753 void ChromeClientEfl::addOrUpdateScrollingLayer(Node*, PlatformLayer* scrollingLayer, PlatformLayer* contentsLayer, const IntSize& scrollSize)
755 ewk_view_add_or_update_scrolling_layer(m_view, scrollingLayer, contentsLayer, scrollSize);
758 void ChromeClientEfl::removeScrollingLayer(Node*, PlatformLayer* scrollingLayer, PlatformLayer* contentsLayer)
760 ewk_view_remove_scrolling_layer(m_view, scrollingLayer, contentsLayer);
764 #if ENABLE(CANVAS_CAIRO_GLES_RENDERING)
765 void* ChromeClientEfl::sharedCairoDevice()
767 return (void*)ewk_view_get_shared_cairo_device(m_view);
772 #if ENABLE(TIZEN_SHOULD_ALLOW_OPEN_URL)
773 bool ChromeClientEfl::shouldAllowOpenUrl(const char* url)
775 return static_cast<bool>(ewk_should_allow_open_uri( m_view, url ));
779 #if ENABLE(FULLSCREEN_API)
780 bool ChromeClientEfl::supportsFullScreenForElement(const WebCore::Element* element, bool withKeyboard)
782 #if ENABLE(TIZEN_FULLSCREEN_API)
783 Settings* settings = ewk_view_core_page_get(m_view)->settings();
784 return settings->fullScreenEnabled();
793 void ChromeClientEfl::enterFullScreenForElement(WebCore::Element* element)
795 element->document()->webkitWillEnterFullScreenForElement(element);
796 element->document()->webkitDidEnterFullScreenForElement(element);
799 void ChromeClientEfl::exitFullScreenForElement(WebCore::Element* element)
801 element->document()->webkitWillExitFullScreenForElement(element);
802 element->document()->webkitDidExitFullScreenForElement(element);