[EFL] Add PageClientEfl to WebCoreSupport.
[WebKit-https.git] / Source / WebKit / efl / WebCoreSupport / ChromeClientEfl.cpp
1 /*
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).
9  *
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
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.
20  *
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.
32  */
33
34 #include "config.h"
35 #include "ChromeClientEfl.h"
36
37 #include "FileChooser.h"
38 #include "FileIconLoader.h"
39 #include "FloatRect.h"
40 #include "FrameLoader.h"
41 #include "FrameLoaderClientEfl.h"
42 #include "HitTestResult.h"
43 #include "IntRect.h"
44 #include "KURL.h"
45 #include "NavigationAction.h"
46 #include "NotImplemented.h"
47 #include "PlatformString.h"
48 #include "PopupMenuEfl.h"
49 #include "SearchPopupMenuEfl.h"
50 #include "SecurityOrigin.h"
51 #include "ViewportArguments.h"
52 #include "WindowFeatures.h"
53 #include "ewk_private.h"
54 #include <Ecore_Evas.h>
55 #include <Evas.h>
56 #include <wtf/text/CString.h>
57
58 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
59 #include "NotificationPresenterClientEfl.h"
60 #endif
61
62 #if ENABLE(SQL_DATABASE)
63 #include "DatabaseDetails.h"
64 #include "DatabaseTracker.h"
65 #endif
66
67 using namespace WebCore;
68
69 static inline Evas_Object* kit(Frame* frame)
70 {
71     if (!frame)
72         return 0;
73
74     FrameLoaderClientEfl* client = static_cast<FrameLoaderClientEfl*>(frame->loader()->client());
75     return client ? client->webFrame() : 0;
76 }
77
78 namespace WebCore {
79
80 ChromeClientEfl::ChromeClientEfl(Evas_Object* view)
81     : m_view(view)
82 {
83     ASSERT(m_view);
84 }
85
86 ChromeClientEfl::~ChromeClientEfl()
87 {
88 }
89
90 void ChromeClientEfl::chromeDestroyed()
91 {
92     delete this;
93 }
94
95 void ChromeClientEfl::focusedNodeChanged(Node*)
96 {
97     notImplemented();
98 }
99
100 void ChromeClientEfl::focusedFrameChanged(Frame*)
101 {
102 }
103
104 FloatRect ChromeClientEfl::windowRect()
105 {
106     Ecore_Evas* ee = 0;
107     int x, y, w, h;
108
109     ee = ecore_evas_ecore_evas_get(evas_object_evas_get(m_view));
110     ecore_evas_geometry_get(ee, &x, &y, &w, &h);
111     return FloatRect(x, y, w, h);
112 }
113
114 void ChromeClientEfl::setWindowRect(const FloatRect& rect)
115 {
116     if (!ewk_view_setting_enable_auto_resize_window_get(m_view))
117         return;
118
119     Ecore_Evas* ee = 0;
120     IntRect intrect = IntRect(rect);
121
122     ee = ecore_evas_ecore_evas_get(evas_object_evas_get(m_view));
123     ecore_evas_move(ee, intrect.x(), intrect.y());
124     ecore_evas_resize(ee, intrect.width(), intrect.height());
125 }
126
127 FloatRect ChromeClientEfl::pageRect()
128 {
129     return ewk_view_page_rect_get(m_view);
130 }
131
132 void ChromeClientEfl::focus()
133 {
134     evas_object_focus_set(m_view, EINA_TRUE);
135 }
136
137 void ChromeClientEfl::unfocus()
138 {
139     evas_object_focus_set(m_view, EINA_FALSE);
140 }
141
142 Page* ChromeClientEfl::createWindow(Frame*, const FrameLoadRequest& frameLoadRequest, const WindowFeatures& features, const NavigationAction&)
143 {
144     Evas_Object* newView = ewk_view_window_create(m_view, EINA_TRUE, &features);
145     if (!newView)
146         return 0;
147
148     return ewk_view_core_page_get(newView);
149 }
150
151 void ChromeClientEfl::show()
152 {
153     ewk_view_ready(m_view);
154 }
155
156 bool ChromeClientEfl::canRunModal()
157 {
158     notImplemented();
159     return false;
160 }
161
162 void ChromeClientEfl::runModal()
163 {
164     notImplemented();
165 }
166
167 void ChromeClientEfl::setToolbarsVisible(bool visible)
168 {
169     ewk_view_toolbars_visible_set(m_view, visible);
170 }
171
172 bool ChromeClientEfl::toolbarsVisible()
173 {
174     bool visible;
175
176     ewk_view_toolbars_visible_get(m_view, &visible);
177     return visible;
178 }
179
180 void ChromeClientEfl::setStatusbarVisible(bool visible)
181 {
182     ewk_view_statusbar_visible_set(m_view, visible);
183 }
184
185 bool ChromeClientEfl::statusbarVisible()
186 {
187     bool visible;
188
189     ewk_view_statusbar_visible_get(m_view, &visible);
190     return visible;
191 }
192
193 void ChromeClientEfl::setScrollbarsVisible(bool visible)
194 {
195     ewk_view_scrollbars_visible_set(m_view, visible);
196 }
197
198 bool ChromeClientEfl::scrollbarsVisible()
199 {
200     bool visible;
201
202     ewk_view_scrollbars_visible_get(m_view, &visible);
203     return visible;
204 }
205
206 void ChromeClientEfl::setMenubarVisible(bool visible)
207 {
208     ewk_view_menubar_visible_set(m_view, visible);
209 }
210
211 bool ChromeClientEfl::menubarVisible()
212 {
213     bool visible;
214
215     ewk_view_menubar_visible_get(m_view, &visible);
216     return visible;
217 }
218
219 void ChromeClientEfl::createSelectPopup(PopupMenuClient* client, int selected, const IntRect& rect)
220 {
221     ewk_view_popup_new(m_view, client, selected, rect);
222 }
223
224 bool ChromeClientEfl::destroySelectPopup()
225 {
226     return ewk_view_popup_destroy(m_view);
227 }
228
229 void ChromeClientEfl::setResizable(bool)
230 {
231     notImplemented();
232 }
233
234 void ChromeClientEfl::closeWindowSoon()
235 {
236     ewk_view_window_close(m_view);
237 }
238
239 bool ChromeClientEfl::canTakeFocus(FocusDirection coreDirection)
240 {
241     // This is called when cycling through links/focusable objects and we
242     // reach the last focusable object.
243     ASSERT(coreDirection == FocusDirectionForward || coreDirection == FocusDirectionBackward);
244
245     Ewk_Focus_Direction direction = static_cast<Ewk_Focus_Direction>(coreDirection);
246
247     return !ewk_view_focus_can_cycle(m_view, direction);
248 }
249
250 void ChromeClientEfl::takeFocus(FocusDirection)
251 {
252     unfocus();
253 }
254
255 bool ChromeClientEfl::canRunBeforeUnloadConfirmPanel()
256 {
257     return true;
258 }
259
260 bool ChromeClientEfl::runBeforeUnloadConfirmPanel(const String& message, Frame* frame)
261 {
262     return runJavaScriptConfirm(frame, message);
263 }
264
265 void ChromeClientEfl::addMessageToConsole(MessageSource, MessageType, MessageLevel, const String& message,
266                                           unsigned int lineNumber, const String& sourceID)
267 {
268     ewk_view_add_console_message(m_view, message.utf8().data(), lineNumber, sourceID.utf8().data());
269 }
270
271 void ChromeClientEfl::runJavaScriptAlert(Frame* frame, const String& message)
272 {
273     ewk_view_run_javascript_alert(m_view, kit(frame), message.utf8().data());
274 }
275
276 bool ChromeClientEfl::runJavaScriptConfirm(Frame* frame, const String& message)
277 {
278     return ewk_view_run_javascript_confirm(m_view, kit(frame), message.utf8().data());
279 }
280
281 bool ChromeClientEfl::runJavaScriptPrompt(Frame* frame, const String& message, const String& defaultValue, String& result)
282 {
283     char* value = 0;
284     ewk_view_run_javascript_prompt(m_view, kit(frame), message.utf8().data(), defaultValue.utf8().data(), &value);
285     if (value) {
286         result = String::fromUTF8(value);
287         free(value);
288         return true;
289     }
290     return false;
291 }
292
293 void ChromeClientEfl::setStatusbarText(const String& string)
294 {
295     ewk_view_statusbar_text_set(m_view, string.utf8().data());
296 }
297
298 bool ChromeClientEfl::shouldInterruptJavaScript()
299 {
300     return ewk_view_should_interrupt_javascript(m_view);
301 }
302
303 KeyboardUIMode ChromeClientEfl::keyboardUIMode()
304 {
305     return KeyboardAccessTabsToLinks;
306 }
307
308 IntRect ChromeClientEfl::windowResizerRect() const
309 {
310     notImplemented();
311     // Implementing this function will make repaint being
312     // called during resize, but as this will be done with
313     // a minor delay it adds a weird "filling" effect due
314     // to us using an evas image for showing the cairo
315     // context. So instead of implementing this function
316     // we call paint directly during resize with
317     // the new object size as its argument.
318     return IntRect();
319 }
320
321 void ChromeClientEfl::contentsSizeChanged(Frame* frame, const IntSize& size) const
322 {
323     ewk_frame_contents_size_changed(kit(frame), size.width(), size.height());
324     if (ewk_view_frame_main_get(m_view) == kit(frame))
325         ewk_view_contents_size_changed(m_view, size.width(), size.height());
326 }
327
328 IntRect ChromeClientEfl::rootViewToScreen(const IntRect& rect) const
329 {
330     notImplemented();
331     return rect;
332 }
333
334 IntPoint ChromeClientEfl::screenToRootView(const IntPoint& point) const
335 {
336     notImplemented();
337     return point;
338 }
339
340 PlatformPageClient ChromeClientEfl::platformPageClient() const
341 {
342     return EWKPrivate::corePageClient(m_view);
343 }
344
345 void ChromeClientEfl::scrollbarsModeDidChange() const
346 {
347 }
348
349 void ChromeClientEfl::mouseDidMoveOverElement(const HitTestResult& hit, unsigned modifierFlags)
350 {
351     // FIXME, compare with old link, look at Qt impl.
352     bool isLink = hit.isLiveLink();
353     if (isLink) {
354         KURL url = hit.absoluteLinkURL();
355         if (!url.isEmpty() && url != m_hoveredLinkURL) {
356             const char* link[2];
357             TextDirection dir;
358             CString urlStr = url.string().utf8();
359             CString titleStr = hit.title(dir).utf8();
360             link[0] = urlStr.data();
361             link[1] = titleStr.data();
362             ewk_view_mouse_link_hover_in(m_view, link);
363             m_hoveredLinkURL = url;
364         }
365     } else if (!isLink && !m_hoveredLinkURL.isEmpty()) {
366         ewk_view_mouse_link_hover_out(m_view);
367         m_hoveredLinkURL = KURL();
368     }
369 }
370
371 void ChromeClientEfl::setToolTip(const String& toolTip, TextDirection)
372 {
373     ewk_view_tooltip_text_set(m_view, toolTip.utf8().data());
374 }
375
376 void ChromeClientEfl::print(Frame* frame)
377 {
378     notImplemented();
379 }
380
381 void ChromeClientEfl::reachedMaxAppCacheSize(int64_t spaceNeeded)
382 {
383     // FIXME: Free some space.
384     notImplemented();
385 }
386
387 void ChromeClientEfl::reachedApplicationCacheOriginQuota(SecurityOrigin*, int64_t)
388 {
389     notImplemented();
390 }
391
392 #if ENABLE(TOUCH_EVENTS)
393 void ChromeClientEfl::needTouchEvents(bool needed)
394 {
395     ewk_view_need_touch_events_set(m_view, needed);
396 }
397 #endif
398
399 #if ENABLE(SQL_DATABASE)
400 void ChromeClientEfl::exceededDatabaseQuota(Frame* frame, const String& databaseName)
401 {
402     uint64_t quota;
403     SecurityOrigin* origin = frame->document()->securityOrigin();
404
405     DatabaseDetails details = DatabaseTracker::tracker().detailsForNameAndOrigin(databaseName, origin);
406     quota = ewk_view_exceeded_database_quota(m_view,
407                                              kit(frame), databaseName.utf8().data(),
408                                              details.currentUsage(), details.expectedUsage());
409
410     /* if client did not set quota, and database is being created now, the
411      * default quota is applied
412      */
413     if (!quota && !DatabaseTracker::tracker().hasEntryForOrigin(origin))
414         quota = ewk_settings_web_database_default_quota_get();
415
416     DatabaseTracker::tracker().setQuota(origin, quota);
417 }
418 #endif
419
420 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
421 NotificationClient* ChromeClientEfl::notificationPresenter() const
422 {
423     notImplemented();
424     return 0;
425 }
426 #endif
427
428 void ChromeClientEfl::runOpenPanel(Frame* frame, PassRefPtr<FileChooser> prpFileChooser)
429 {
430     RefPtr<FileChooser> chooser = prpFileChooser;
431     Eina_List* selectedFilenames = 0;
432     void* filename;
433     Vector<String> filenames;
434
435     const FileChooserSettings& settings = chooser->settings();
436     bool confirm = ewk_view_run_open_panel(m_view, kit(frame), settings.allowsMultipleFiles, settings.acceptMIMETypes, &selectedFilenames);
437
438     if (!confirm)
439         return;
440
441     EINA_LIST_FREE(selectedFilenames, filename) {
442         filenames.append((char*)filename);
443         free(filename);
444     }
445
446     if (chooser->settings().allowsMultipleFiles)
447         chooser->chooseFiles(filenames);
448     else
449         chooser->chooseFile(filenames[0]);
450 }
451
452 void ChromeClientEfl::formStateDidChange(const Node*)
453 {
454     notImplemented();
455 }
456
457 void ChromeClientEfl::setCursor(const Cursor&)
458 {
459     notImplemented();
460 }
461
462 void ChromeClientEfl::setCursorHiddenUntilMouseMoves(bool)
463 {
464     notImplemented();
465 }
466
467 void ChromeClientEfl::cancelGeolocationPermissionForFrame(Frame*, Geolocation*)
468 {
469     notImplemented();
470 }
471
472 void ChromeClientEfl::invalidateContents(const IntRect& updateRect, bool immediate)
473 {
474     notImplemented();
475 }
476
477 void ChromeClientEfl::invalidateRootView(const IntRect& updateRect, bool immediate)
478 {
479     notImplemented();
480 }
481
482 void ChromeClientEfl::invalidateContentsAndRootView(const IntRect& updateRect, bool immediate)
483 {
484     if (updateRect.isEmpty())
485         return;
486
487     Evas_Coord x, y, w, h;
488
489     x = updateRect.x();
490     y = updateRect.y();
491     w = updateRect.width();
492     h = updateRect.height();
493     ewk_view_repaint(m_view, x, y, w, h);
494 }
495
496 void ChromeClientEfl::invalidateContentsForSlowScroll(const IntRect& updateRect, bool immediate)
497 {
498     invalidateContentsAndRootView(updateRect, immediate);
499 }
500
501 void ChromeClientEfl::scroll(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
502 {
503     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());
504 }
505
506 void ChromeClientEfl::cancelGeolocationPermissionRequestForFrame(Frame*)
507 {
508     notImplemented();
509 }
510
511 void ChromeClientEfl::iconForFiles(const Vector<String, 0u>&, PassRefPtr<FileChooser>)
512 {
513     notImplemented();
514 }
515
516 void ChromeClientEfl::loadIconForFiles(const Vector<String>&, FileIconLoader*)
517 {
518     notImplemented();
519 }
520
521 void ChromeClientEfl::dispatchViewportPropertiesDidChange(const ViewportArguments& arguments) const
522 {
523     ewk_view_viewport_attributes_set(m_view, arguments);
524 }
525
526 bool ChromeClientEfl::selectItemWritingDirectionIsNatural()
527 {
528     return true;
529 }
530
531 bool ChromeClientEfl::selectItemAlignmentFollowsMenuWritingDirection()
532 {
533     return false;
534 }
535
536 bool ChromeClientEfl::hasOpenedPopup() const
537 {
538     notImplemented();
539     return false;
540 }
541
542 PassRefPtr<PopupMenu> ChromeClientEfl::createPopupMenu(PopupMenuClient* client) const
543 {
544     return adoptRef(new PopupMenuEfl(client));
545 }
546
547 PassRefPtr<SearchPopupMenu> ChromeClientEfl::createSearchPopupMenu(PopupMenuClient* client) const
548 {
549     return adoptRef(new SearchPopupMenuEfl(client));
550 }
551
552 #if USE(ACCELERATED_COMPOSITING)
553 void ChromeClientEfl::attachRootGraphicsLayer(Frame* frame, GraphicsLayer* rootLayer)
554 {
555     notImplemented();
556 }
557
558 void ChromeClientEfl::setNeedsOneShotDrawingSynchronization()
559 {
560     notImplemented();
561 }
562
563 void ChromeClientEfl::scheduleCompositingLayerSync()
564 {
565     notImplemented();
566 }
567
568 ChromeClient::CompositingTriggerFlags ChromeClientEfl::allowedCompositingTriggers() const
569 {
570     return 0;
571 }
572 #endif
573
574 #if ENABLE(FULLSCREEN_API)
575 bool ChromeClientEfl::supportsFullScreenForElement(const WebCore::Element* element, bool withKeyboard)
576 {
577     if (withKeyboard)
578         return false;
579
580     return true;
581 }
582
583 void ChromeClientEfl::enterFullScreenForElement(WebCore::Element* element)
584 {
585     element->document()->webkitWillEnterFullScreenForElement(element);
586     element->document()->webkitDidEnterFullScreenForElement(element);
587 }
588
589 void ChromeClientEfl::exitFullScreenForElement(WebCore::Element* element)
590 {
591     element->document()->webkitWillExitFullScreenForElement(element);
592     element->document()->webkitDidExitFullScreenForElement(element);
593 }
594 #endif
595 }