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