blob: 6459887a5ad8ed72f69063322c8559c8908746c8 [file] [log] [blame]
/*
* Copyright (C) 2006 Zack Rusin <zack@kde.org>
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
* Copyright (C) 2008 Kenneth Rohde Christiansen
* Copyright (C) 2008 Diego Gonzalez
* Copyright (C) 2009-2010 ProFUSION embedded systems
* Copyright (C) 2009-2010 Samsung Electronics
* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "ChromeClientEfl.h"
#if ENABLE(DATABASE)
#include "DatabaseDetails.h"
#include "DatabaseTracker.h"
#endif
#include "EWebKit.h"
#include "FileChooser.h"
#include "FloatRect.h"
#include "FrameLoader.h"
#include "FrameLoaderClientEfl.h"
#include "HitTestResult.h"
#include "IntRect.h"
#include "KURL.h"
#include "NavigationAction.h"
#include "NotImplemented.h"
#include "PlatformString.h"
#include "SecurityOrigin.h"
#include "PopupMenuEfl.h"
#include "SearchPopupMenuEfl.h"
#include "ViewportArguments.h"
#include "WindowFeatures.h"
#include "ewk_private.h"
#include <Ecore_Evas.h>
#include <Evas.h>
#include <wtf/text/CString.h>
using namespace WebCore;
static inline Evas_Object* kit(Frame* frame)
{
if (!frame)
return 0;
FrameLoaderClientEfl* client = static_cast<FrameLoaderClientEfl*>(frame->loader()->client());
return client ? client->webFrame() : 0;
}
namespace WebCore {
ChromeClientEfl::ChromeClientEfl(Evas_Object* view)
: m_view(view)
{
}
ChromeClientEfl::~ChromeClientEfl()
{
}
void ChromeClientEfl::chromeDestroyed()
{
delete this;
}
void ChromeClientEfl::focusedNodeChanged(Node*)
{
notImplemented();
}
void ChromeClientEfl::focusedFrameChanged(Frame*)
{
}
FloatRect ChromeClientEfl::windowRect()
{
Ecore_Evas* ee = 0;
int x, y, w, h;
if (!m_view)
return FloatRect();
ee = ecore_evas_ecore_evas_get(evas_object_evas_get(m_view));
ecore_evas_geometry_get(ee, &x, &y, &w, &h);
return FloatRect(x, y, w, h);
}
void ChromeClientEfl::setWindowRect(const FloatRect& rect)
{
Ecore_Evas* ee = 0;
IntRect intrect = IntRect(rect);
if (!m_view)
return;
if (!ewk_view_setting_enable_auto_resize_window_get(m_view))
return;
ee = ecore_evas_ecore_evas_get(evas_object_evas_get(m_view));
ecore_evas_move(ee, intrect.x(), intrect.y());
ecore_evas_resize(ee, intrect.width(), intrect.height());
}
FloatRect ChromeClientEfl::pageRect()
{
if (!m_view)
return FloatRect();
return ewk_view_page_rect_get(m_view);
}
float ChromeClientEfl::scaleFactor()
{
notImplemented();
return 1.0;
}
void ChromeClientEfl::focus()
{
evas_object_focus_set(m_view, EINA_TRUE);
}
void ChromeClientEfl::unfocus()
{
evas_object_focus_set(m_view, EINA_FALSE);
}
Page* ChromeClientEfl::createWindow(Frame*, const FrameLoadRequest& frameLoadRequest, const WindowFeatures& features, const NavigationAction&)
{
Evas_Object* newView = ewk_view_window_create(m_view, EINA_TRUE, &features);
if (!newView)
return 0;
return ewk_view_core_page_get(newView);
}
void ChromeClientEfl::show()
{
ewk_view_ready(m_view);
}
bool ChromeClientEfl::canRunModal()
{
notImplemented();
return false;
}
void ChromeClientEfl::runModal()
{
notImplemented();
}
void ChromeClientEfl::setToolbarsVisible(bool visible)
{
ewk_view_toolbars_visible_set(m_view, visible);
}
bool ChromeClientEfl::toolbarsVisible()
{
Eina_Bool visible;
ewk_view_toolbars_visible_get(m_view, &visible);
return visible;
}
void ChromeClientEfl::setStatusbarVisible(bool visible)
{
ewk_view_statusbar_visible_set(m_view, visible);
}
bool ChromeClientEfl::statusbarVisible()
{
Eina_Bool visible;
ewk_view_statusbar_visible_get(m_view, &visible);
return visible;
}
void ChromeClientEfl::setScrollbarsVisible(bool visible)
{
ewk_view_scrollbars_visible_set(m_view, visible);
}
bool ChromeClientEfl::scrollbarsVisible()
{
Eina_Bool visible;
ewk_view_scrollbars_visible_get(m_view, &visible);
return visible;
}
void ChromeClientEfl::setMenubarVisible(bool visible)
{
ewk_view_menubar_visible_set(m_view, visible);
}
bool ChromeClientEfl::menubarVisible()
{
Eina_Bool visible;
ewk_view_menubar_visible_get(m_view, &visible);
return visible;
}
void ChromeClientEfl::createSelectPopup(PopupMenuClient* client, int selected, const IntRect& rect)
{
ewk_view_popup_new(m_view, client, selected, rect);
}
bool ChromeClientEfl::destroySelectPopup()
{
return ewk_view_popup_destroy(m_view);
}
void ChromeClientEfl::setResizable(bool)
{
notImplemented();
}
void ChromeClientEfl::closeWindowSoon()
{
ewk_view_window_close(m_view);
}
bool ChromeClientEfl::canTakeFocus(FocusDirection)
{
// This is called when cycling through links/focusable objects and we
// reach the last focusable object.
return false;
}
void ChromeClientEfl::takeFocus(FocusDirection)
{
unfocus();
}
bool ChromeClientEfl::canRunBeforeUnloadConfirmPanel()
{
return true;
}
bool ChromeClientEfl::runBeforeUnloadConfirmPanel(const String& message, Frame* frame)
{
return runJavaScriptConfirm(frame, message);
}
void ChromeClientEfl::addMessageToConsole(MessageSource, MessageType, MessageLevel, const String& message,
unsigned int lineNumber, const String& sourceID)
{
ewk_view_add_console_message(m_view, message.utf8().data(), lineNumber, sourceID.utf8().data());
}
void ChromeClientEfl::runJavaScriptAlert(Frame* frame, const String& message)
{
ewk_view_run_javascript_alert(m_view, kit(frame), message.utf8().data());
}
bool ChromeClientEfl::runJavaScriptConfirm(Frame* frame, const String& message)
{
return ewk_view_run_javascript_confirm(m_view, kit(frame), message.utf8().data());
}
bool ChromeClientEfl::runJavaScriptPrompt(Frame* frame, const String& message, const String& defaultValue, String& result)
{
char* value = 0;
ewk_view_run_javascript_prompt(m_view, kit(frame), message.utf8().data(), defaultValue.utf8().data(), &value);
if (value) {
result = String::fromUTF8(value);
free(value);
return true;
}
return false;
}
void ChromeClientEfl::setStatusbarText(const String& string)
{
ewk_view_statusbar_text_set(m_view, string.utf8().data());
}
bool ChromeClientEfl::shouldInterruptJavaScript()
{
return ewk_view_should_interrupt_javascript(m_view);
}
KeyboardUIMode ChromeClientEfl::keyboardUIMode()
{
return KeyboardAccessTabsToLinks;
}
IntRect ChromeClientEfl::windowResizerRect() const
{
notImplemented();
// Implementing this function will make repaint being
// called during resize, but as this will be done with
// a minor delay it adds a weird "filling" effect due
// to us using an evas image for showing the cairo
// context. So instead of implementing this function
// we call paint directly during resize with
// the new object size as its argument.
return IntRect();
}
void ChromeClientEfl::contentsSizeChanged(Frame* frame, const IntSize& size) const
{
ewk_frame_contents_size_changed(kit(frame), size.width(), size.height());
if (ewk_view_frame_main_get(m_view) == kit(frame))
ewk_view_contents_size_changed(m_view, size.width(), size.height());
}
IntRect ChromeClientEfl::windowToScreen(const IntRect& rect) const
{
notImplemented();
return rect;
}
IntPoint ChromeClientEfl::screenToWindow(const IntPoint& point) const
{
notImplemented();
return point;
}
PlatformPageClient ChromeClientEfl::platformPageClient() const
{
return m_view;
}
void ChromeClientEfl::scrollbarsModeDidChange() const
{
}
void ChromeClientEfl::mouseDidMoveOverElement(const HitTestResult& hit, unsigned modifierFlags)
{
// FIXME, compare with old link, look at Qt impl.
bool isLink = hit.isLiveLink();
if (isLink) {
KURL url = hit.absoluteLinkURL();
if (!url.isEmpty() && url != m_hoveredLinkURL) {
const char* link[2];
TextDirection dir;
CString urlStr = url.string().utf8();
CString titleStr = hit.title(dir).utf8();
link[0] = urlStr.data();
link[1] = titleStr.data();
ewk_view_mouse_link_hover_in(m_view, link);
m_hoveredLinkURL = url;
}
} else if (!isLink && !m_hoveredLinkURL.isEmpty()) {
ewk_view_mouse_link_hover_out(m_view);
m_hoveredLinkURL = KURL();
}
}
void ChromeClientEfl::setToolTip(const String& toolTip, TextDirection)
{
ewk_view_tooltip_text_set(m_view, toolTip.utf8().data());
}
void ChromeClientEfl::print(Frame* frame)
{
notImplemented();
}
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
void ChromeClientEfl::reachedMaxAppCacheSize(int64_t spaceNeeded)
{
// FIXME: Free some space.
notImplemented();
}
void ChromeClientEfl::reachedApplicationCacheOriginQuota(SecurityOrigin*)
{
notImplemented();
}
#endif
#if ENABLE(TOUCH_EVENTS)
void ChromeClientEfl::needTouchEvents(bool needed)
{
ewk_view_need_touch_events_set(m_view, needed);
}
#endif
#if ENABLE(DATABASE)
void ChromeClientEfl::exceededDatabaseQuota(Frame* frame, const String& databaseName)
{
uint64_t quota;
SecurityOrigin* origin = frame->document()->securityOrigin();
DatabaseDetails details = DatabaseTracker::tracker().detailsForNameAndOrigin(databaseName, origin);
quota = ewk_view_exceeded_database_quota(m_view,
kit(frame), databaseName.utf8().data(),
details.currentUsage(), details.expectedUsage());
/* if client did not set quota, and database is being created now, the
* default quota is applied
*/
if (!quota && !DatabaseTracker::tracker().hasEntryForOrigin(origin))
quota = ewk_settings_web_database_default_quota_get();
DatabaseTracker::tracker().setQuota(origin, quota);
}
#endif
void ChromeClientEfl::runOpenPanel(Frame* frame, PassRefPtr<FileChooser> prpFileChooser)
{
RefPtr<FileChooser> chooser = prpFileChooser;
bool confirm;
Eina_List* selectedFilenames = 0;
Eina_List* suggestedFilenames = 0;
void* filename;
Vector<String> filenames;
for (unsigned i = 0; i < chooser->filenames().size(); i++) {
CString str = chooser->filenames()[i].utf8();
filename = strdup(str.data());
suggestedFilenames = eina_list_append(suggestedFilenames, filename);
}
confirm = ewk_view_run_open_panel(m_view, kit(frame), chooser->allowsMultipleFiles(), suggestedFilenames, &selectedFilenames);
EINA_LIST_FREE(suggestedFilenames, filename)
free(filename);
if (!confirm)
return;
EINA_LIST_FREE(selectedFilenames, filename) {
filenames.append((char *)filename);
free(filename);
}
if (chooser->allowsMultipleFiles())
chooser->chooseFiles(filenames);
else
chooser->chooseFile(filenames[0]);
}
void ChromeClientEfl::formStateDidChange(const Node*)
{
notImplemented();
}
void ChromeClientEfl::setCursor(const Cursor&)
{
notImplemented();
}
void ChromeClientEfl::requestGeolocationPermissionForFrame(Frame*, Geolocation*)
{
// See the comment in WebCore/page/ChromeClient.h
notImplemented();
}
void ChromeClientEfl::cancelGeolocationPermissionRequestForFrame(Frame*, Geolocation*)
{
notImplemented();
}
void ChromeClientEfl::cancelGeolocationPermissionForFrame(Frame*, Geolocation*)
{
notImplemented();
}
void ChromeClientEfl::invalidateContents(const IntRect& updateRect, bool immediate)
{
notImplemented();
}
void ChromeClientEfl::invalidateWindow(const IntRect& updateRect, bool immediate)
{
notImplemented();
}
void ChromeClientEfl::invalidateContentsAndWindow(const IntRect& updateRect, bool immediate)
{
Evas_Coord x, y, w, h;
x = updateRect.x();
y = updateRect.y();
w = updateRect.width();
h = updateRect.height();
ewk_view_repaint(m_view, x, y, w, h);
}
void ChromeClientEfl::invalidateContentsForSlowScroll(const IntRect& updateRect, bool immediate)
{
invalidateContentsAndWindow(updateRect, immediate);
}
void ChromeClientEfl::scroll(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
{
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);
}
void ChromeClientEfl::cancelGeolocationPermissionRequestForFrame(Frame*)
{
notImplemented();
}
void ChromeClientEfl::iconForFiles(const Vector<String, 0u>&, PassRefPtr<FileChooser>)
{
notImplemented();
}
void ChromeClientEfl::chooseIconForFiles(const Vector<String>&, FileChooser*)
{
notImplemented();
}
void ChromeClientEfl::dispatchViewportDataDidChange(const ViewportArguments& arguments) const
{
ewk_view_viewport_attributes_set(m_view, arguments);
}
bool ChromeClientEfl::selectItemWritingDirectionIsNatural()
{
return true;
}
bool ChromeClientEfl::selectItemAlignmentFollowsMenuWritingDirection()
{
return false;
}
PassRefPtr<PopupMenu> ChromeClientEfl::createPopupMenu(PopupMenuClient* client) const
{
return adoptRef(new PopupMenuEfl(client));
}
PassRefPtr<SearchPopupMenu> ChromeClientEfl::createSearchPopupMenu(PopupMenuClient* client) const
{
return adoptRef(new SearchPopupMenuEfl(client));
}
}