Revert "[CherryPick] Input Method upversion"
[framework/web/webkit-efl.git] / Source / WebKit / efl / ewk / ewk_frame.cpp
1 /*
2     Copyright (C) 2009-2010 ProFUSION embedded systems
3     Copyright (C) 2009-2010 Samsung Electronics
4
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Library General Public
7     License as published by the Free Software Foundation; either
8     version 2 of the License, or (at your option) any later version.
9
10     This library is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13     Library General Public License for more details.
14
15     You should have received a copy of the GNU Library General Public License
16     along with this library; see the file COPYING.LIB.  If not, write to
17     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18     Boston, MA 02110-1301, USA.
19 */
20
21 // Uncomment to view frame regions and debug messages
22 // #define EWK_FRAME_DEBUG
23
24 #include "config.h"
25 #include "ewk_frame.h"
26
27 #include "DOMWindowIntents.h"
28 #include "DeliveredIntent.h"
29 #include "DocumentLoader.h"
30 #include "DocumentMarkerController.h"
31 #include "EventHandler.h"
32 #include "FocusController.h"
33 #include "FrameLoaderClientEfl.h"
34 #include "FrameView.h"
35 #include "HTMLCollection.h"
36 #include "HTMLHeadElement.h"
37 #include "HTMLImageElement.h"
38 #include "HTMLNames.h"
39 #include "HTMLPlugInElement.h"
40 #include "HistoryItem.h"
41 #include "HitTestResult.h"
42 #include "IntSize.h"
43 #include "KURL.h"
44 #include "PlatformEvent.h"
45 #include "PlatformKeyboardEvent.h"
46 #include "PlatformMessagePortChannel.h"
47 #include "PlatformMouseEvent.h"
48 #include "PlatformTouchEvent.h"
49 #include "PlatformWheelEvent.h"
50 #include "ProgressTracker.h"
51 #include "ResourceRequest.h"
52 #include "ScriptValue.h"
53 #include "SharedBuffer.h"
54 #include "SubstituteData.h"
55 #include "WindowsKeyboardCodes.h"
56 #include "ewk_frame_private.h"
57 #include "ewk_intent_private.h"
58 #include "ewk_private.h"
59 #include "ewk_security_origin_private.h"
60 #include "ewk_view_private.h"
61 #include <Ecore_Input.h>
62 #include <Eina.h>
63 #include <Evas.h>
64 #include <eina_safety_checks.h>
65 #include <wtf/Assertions.h>
66 #include <wtf/PassRefPtr.h>
67 #include <wtf/RefPtr.h>
68 #include <wtf/Vector.h>
69 #include <wtf/text/CString.h>
70
71 static const char EWK_FRAME_TYPE_STR[] = "EWK_Frame";
72
73 struct Ewk_Frame_Smart_Data {
74     Evas_Object_Smart_Clipped_Data base;
75     Evas_Object* self;
76     Evas_Object* view;
77 #ifdef EWK_FRAME_DEBUG
78     Evas_Object* region;
79 #endif
80     WebCore::Frame* frame;
81     Ewk_Text_With_Direction title;
82     const char* uri;
83     const char* name;
84     bool editable : 1;
85     bool hasDisplayedMixedContent : 1;
86     bool hasRunMixedContent : 1;
87 };
88
89 struct Eina_Iterator_Ewk_Frame {
90     Eina_Iterator base;
91     Evas_Object* object;
92     unsigned currentIndex;
93 };
94
95 #ifndef EWK_TYPE_CHECK
96 #define EWK_FRAME_TYPE_CHECK(ewkFrame, ...) do { } while (0)
97 #else
98 #define EWK_FRAME_TYPE_CHECK(ewkFrame, ...) \
99     do { \
100         const char* _tmp_otype = evas_object_type_get(ewkFrame); \
101         if (EINA_UNLIKELY(_tmp_otype != EWK_FRAME_TYPE_STR)) { \
102             EINA_LOG_CRIT \
103                 ("%p (%s) is not of an ewk_frame!", ewkFrame, \
104                 _tmp_otype ? _tmp_otype : "(null)"); \
105             return __VA_ARGS__; \
106         } \
107     } while (0)
108 #endif
109
110 #define EWK_FRAME_SD_GET(ewkFrame, pointer) \
111     Ewk_Frame_Smart_Data* pointer = static_cast<Ewk_Frame_Smart_Data*>(evas_object_smart_data_get(ewkFrame))
112
113 #define EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, pointer, ...) \
114     EWK_FRAME_TYPE_CHECK(ewkFrame, __VA_ARGS__); \
115     EWK_FRAME_SD_GET(ewkFrame, pointer); \
116     if (!pointer) { \
117         CRITICAL("no smart data for object %p (%s)", \
118                  ewkFrame, evas_object_type_get(ewkFrame)); \
119         return __VA_ARGS__; \
120     }
121
122 static Evas_Smart_Class _parent_sc = EVAS_SMART_CLASS_INIT_NULL;
123
124 #ifdef EWK_FRAME_DEBUG
125 static inline void _ewk_frame_debug(Evas_Object* ewkFrame)
126 {
127     Evas_Object* clip, * parent;
128     Evas_Coord x, y, width, height, contentX, contentY, contentWidth, contentHeight;
129     int red, green, blue, alpha, contentRed, contentGreen, contentBlue, contentAlpha;
130
131     evas_object_color_get(ewkFrame, &red, &green, &blue, &alpha);
132     evas_object_geometry_get(ewkFrame, &x, &y, &width, &height);
133
134     clip = evas_object_clip_get(ewkFrame);
135     evas_object_color_get(clip, &contentRed, &contentGreen, &contentBlue, &contentAlpha);
136     evas_object_geometry_get(clip, &contentX, &contentY, &contentWidth, &contentHeight);
137
138     fprintf(stderr, "%p: type=%s name=%s, visible=%d, color=%02x%02x%02x%02x, %d,%d+%dx%d, clipper=%p (%d, %02x%02x%02x%02x, %d,%d+%dx%d)\n",
139             ewkFrame, evas_object_type_get(ewkFrame), evas_object_name_get(ewkFrame), evas_object_visible_get(ewkFrame),
140             red, green, blue, alpha, x, y, width, height,
141             clip, evas_object_visible_get(clip), contentRed, contentGreen, contentBlue, contentAlpha, contentX, contentY, contentWidth, contentHeight);
142     parent = evas_object_smart_parent_get(ewkFrame);
143     if (!parent)
144         fprintf(stderr, "\n");
145     else
146         _ewk_frame_debug(parent);
147 }
148 #endif
149
150 static WebCore::FrameLoaderClientEfl* _ewk_frame_loader_efl_get(const WebCore::Frame* frame)
151 {
152     return static_cast<WebCore::FrameLoaderClientEfl*>(frame->loader()->client());
153 }
154
155 static Eina_Bool _ewk_frame_children_iterator_next(Eina_Iterator_Ewk_Frame* iterator, Evas_Object** data)
156 {
157     EWK_FRAME_SD_GET_OR_RETURN(iterator->object, smartData, false);
158     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
159
160     WebCore::FrameTree* tree = smartData->frame->tree(); // check if it's still valid
161     EINA_SAFETY_ON_NULL_RETURN_VAL(tree, false);
162
163     if (iterator->currentIndex < tree->childCount()) {
164         *data = EWKPrivate::kitFrame(tree->child(iterator->currentIndex++));
165         return true;
166     }
167
168     return false;
169 }
170
171 static Evas_Object* _ewk_frame_children_iterator_get_container(Eina_Iterator_Ewk_Frame* iterator)
172 {
173     return iterator->object;
174 }
175
176 static void _ewk_frame_smart_add(Evas_Object* ewkFrame)
177 {
178     EWK_FRAME_SD_GET(ewkFrame, smartData);
179
180     if (!smartData) {
181         smartData = static_cast<Ewk_Frame_Smart_Data*>(calloc(1, sizeof(Ewk_Frame_Smart_Data)));
182         if (!smartData) {
183             CRITICAL("could not allocate Ewk_Frame_Smart_Data");
184             return;
185         }
186         evas_object_smart_data_set(ewkFrame, smartData);
187     }
188
189     smartData->self = ewkFrame;
190
191     _parent_sc.add(ewkFrame);
192     evas_object_static_clip_set(smartData->base.clipper, false);
193     evas_object_move(smartData->base.clipper, 0, 0);
194     evas_object_resize(smartData->base.clipper, 0, 0);
195
196 #ifdef EWK_FRAME_DEBUG
197     smartData->region = evas_object_rectangle_add(smartData->base.evas);
198     static int i = 0;
199     switch (i) {
200     case 0:
201         evas_object_color_set(smartData->region, 128, 0, 0, 128);
202         break;
203     case 1:
204         evas_object_color_set(smartData->region, 0, 128, 0, 128);
205         break;
206     case 2:
207         evas_object_color_set(smartData->region, 0, 0, 128, 128);
208         break;
209     case 3:
210         evas_object_color_set(smartData->region, 128, 0, 0, 128);
211         break;
212     case 4:
213         evas_object_color_set(smartData->region, 128, 128, 0, 128);
214         break;
215     case 5:
216         evas_object_color_set(smartData->region, 128, 0, 128, 128);
217         break;
218     case 6:
219         evas_object_color_set(smartData->region, 0, 128, 128, 128);
220         break;
221     default:
222         break;
223     }
224     i++;
225     if (i > 6)
226         i = 0;
227
228     evas_object_smart_member_add(smartData->region, ewkFrame);
229     evas_object_hide(smartData->region);
230 #endif
231 }
232
233 static void _ewk_frame_smart_del(Evas_Object* ewkFrame)
234 {
235     EWK_FRAME_SD_GET(ewkFrame, smartData);
236
237     if (smartData) {
238         if (smartData->frame) {
239             WebCore::FrameLoaderClientEfl* flc = _ewk_frame_loader_efl_get(smartData->frame);
240             flc->setWebFrame(0);
241             EWK_FRAME_SD_GET(ewk_view_frame_main_get(smartData->view), mainSmartData);
242             if (mainSmartData->frame == smartData->frame) // applying only for main frame is enough (will traverse through frame tree)
243                 smartData->frame->loader()->detachFromParent();
244             smartData->frame = 0;
245         }
246
247         eina_stringshare_del(smartData->title.string);
248         eina_stringshare_del(smartData->uri);
249         eina_stringshare_del(smartData->name);
250     }
251
252     _parent_sc.del(ewkFrame);
253 }
254
255 static void _ewk_frame_smart_resize(Evas_Object* ewkFrame, Evas_Coord width, Evas_Coord height)
256 {
257     EWK_FRAME_SD_GET(ewkFrame, smartData);
258     evas_object_resize(smartData->base.clipper, width, height);
259
260 #ifdef EWK_FRAME_DEBUG
261     evas_object_resize(smartData->region, width, height);
262     Evas_Coord x, y;
263     evas_object_geometry_get(smartData->region, &x, &y, &width, &height);
264     INF("region=%p, visible=%d, geo=%d,%d + %dx%d",
265         smartData->region, evas_object_visible_get(smartData->region), x, y, width, height);
266     _ewk_frame_debug(ewkFrame);
267 #endif
268 }
269
270 static void _ewk_frame_smart_set(Evas_Smart_Class* api)
271 {
272     evas_object_smart_clipped_smart_set(api);
273     api->add = _ewk_frame_smart_add;
274     api->del = _ewk_frame_smart_del;
275     api->resize = _ewk_frame_smart_resize;
276 }
277
278 static inline Evas_Smart* _ewk_frame_smart_class_new(void)
279 {
280     static Evas_Smart_Class smartClass = EVAS_SMART_CLASS_INIT_NAME_VERSION(EWK_FRAME_TYPE_STR);
281     static Evas_Smart* smart = 0;
282
283     if (EINA_UNLIKELY(!smart)) {
284         evas_object_smart_clipped_smart_set(&_parent_sc);
285         _ewk_frame_smart_set(&smartClass);
286         smart = evas_smart_class_new(&smartClass);
287     }
288
289     return smart;
290 }
291
292 Evas_Object* ewk_frame_view_get(const Evas_Object* ewkFrame)
293 {
294     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, 0);
295     return smartData->view;
296 }
297
298 Ewk_Security_Origin* ewk_frame_security_origin_get(const Evas_Object *ewkFrame)
299 {
300     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, 0);
301     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, 0);
302     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame->document(), 0);
303     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame->document()->securityOrigin(), 0);
304
305     return ewk_security_origin_new(smartData->frame->document()->securityOrigin());
306 }
307
308 Eina_Iterator* ewk_frame_children_iterator_new(Evas_Object* ewkFrame)
309 {
310     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, 0);
311     Eina_Iterator_Ewk_Frame* iterator = static_cast<Eina_Iterator_Ewk_Frame*>
312                                   (calloc(1, sizeof(Eina_Iterator_Ewk_Frame)));
313     if (!iterator)
314         return 0;
315
316     EINA_MAGIC_SET(&iterator->base, EINA_MAGIC_ITERATOR);
317     iterator->base.next = FUNC_ITERATOR_NEXT(_ewk_frame_children_iterator_next);
318     iterator->base.get_container = FUNC_ITERATOR_GET_CONTAINER(_ewk_frame_children_iterator_get_container);
319     iterator->base.free = FUNC_ITERATOR_FREE(free);
320     iterator->object = ewkFrame;
321     iterator->currentIndex = 0;
322     return &iterator->base;
323 }
324
325 Evas_Object* ewk_frame_child_find(Evas_Object* ewkFrame, const char* name)
326 {
327     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, 0);
328     EINA_SAFETY_ON_NULL_RETURN_VAL(name, 0);
329     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, 0);
330     WTF::String frameName = WTF::String::fromUTF8(name);
331     return EWKPrivate::kitFrame(smartData->frame->tree()->find(WTF::AtomicString(frameName)));
332 }
333
334 Eina_Bool ewk_frame_uri_set(Evas_Object* ewkFrame, const char* uri)
335 {
336     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
337     WebCore::KURL kurl(WebCore::KURL(), WTF::String::fromUTF8(uri));
338     WebCore::ResourceRequest req(kurl);
339     WebCore::FrameLoader* loader = smartData->frame->loader();
340     loader->load(req, false);
341     return true;
342 }
343
344 const char* ewk_frame_uri_get(const Evas_Object* ewkFrame)
345 {
346     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, 0);
347     return smartData->uri;
348 }
349
350 const Ewk_Text_With_Direction* ewk_frame_title_get(const Evas_Object* ewkFrame)
351 {
352     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, 0);
353     return &smartData->title;
354 }
355
356 const char* ewk_frame_name_get(const Evas_Object* ewkFrame)
357 {
358     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, 0);
359
360     if (!smartData->frame) {
361         ERR("could not get name of uninitialized frame.");
362         return 0;
363     }
364
365     const WTF::String frameName = smartData->frame->tree()->uniqueName();
366
367     if ((smartData->name) && (smartData->name == frameName))
368         return smartData->name;
369
370     eina_stringshare_replace_length(&(smartData->name), frameName.utf8().data(), frameName.length());
371
372     return smartData->name;
373 }
374
375 Eina_Bool ewk_frame_contents_size_get(const Evas_Object* ewkFrame, Evas_Coord* width, Evas_Coord* height)
376 {
377     if (width)
378         *width = 0;
379     if (height)
380         *height = 0;
381     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
382     if (!smartData->frame || !smartData->frame->view())
383         return false;
384     if (width)
385         *width = smartData->frame->view()->contentsWidth();
386     if (height)
387         *height = smartData->frame->view()->contentsHeight();
388     return true;
389 }
390
391 static Eina_Bool _ewk_frame_contents_set_internal(Ewk_Frame_Smart_Data* smartData, const char* contents, size_t contentsSize, const char* mimeType, const char* encoding, const char* baseUri, const char* unreachableUri)
392 {
393     size_t length = strlen(contents);
394     if (contentsSize < 1 || contentsSize > length)
395         contentsSize = length;
396     if (!mimeType)
397         mimeType = "text/html";
398     if (!encoding)
399         encoding = "UTF-8";
400     if (!baseUri)
401         baseUri = "about:blank";
402
403     WebCore::KURL baseKURL(WebCore::KURL(), WTF::String::fromUTF8(baseUri));
404     WebCore::KURL unreachableKURL;
405     if (unreachableUri)
406         unreachableKURL = WebCore::KURL(WebCore::KURL(), WTF::String::fromUTF8(unreachableUri));
407     else
408         unreachableKURL = WebCore::KURL();
409
410     WTF::RefPtr<WebCore::SharedBuffer> buffer = WebCore::SharedBuffer::create(contents, contentsSize);
411     WebCore::SubstituteData substituteData
412         (buffer.release(),
413         WTF::String::fromUTF8(mimeType),
414         WTF::String::fromUTF8(encoding),
415         baseKURL, unreachableKURL);
416     WebCore::ResourceRequest request(baseKURL);
417
418     smartData->frame->loader()->load(request, substituteData, false);
419     return true;
420 }
421
422 Eina_Bool ewk_frame_contents_set(Evas_Object* ewkFrame, const char* contents, size_t contentsSize, const char* mimeType, const char* encoding, const char* baseUri)
423 {
424     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
425     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
426     EINA_SAFETY_ON_NULL_RETURN_VAL(contents, false);
427     return _ewk_frame_contents_set_internal
428                (smartData, contents, contentsSize, mimeType, encoding, baseUri, 0);
429 }
430
431 Eina_Bool ewk_frame_contents_alternate_set(Evas_Object* ewkFrame, const char* contents, size_t contentsSize, const char* mimeType, const char* encoding, const char* baseUri, const char* unreachableUri)
432 {
433     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
434     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
435     EINA_SAFETY_ON_NULL_RETURN_VAL(contents, false);
436     EINA_SAFETY_ON_NULL_RETURN_VAL(unreachableUri, false);
437     return _ewk_frame_contents_set_internal
438                (smartData, contents, contentsSize, mimeType, encoding, baseUri,
439                unreachableUri);
440 }
441
442 const char* ewk_frame_script_execute(Evas_Object* ewkFrame, const char* script)
443 {
444     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, 0);
445     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, 0);
446     EINA_SAFETY_ON_NULL_RETURN_VAL(script, 0);
447
448 #if USE(JSC)
449     WTF::String resultString;
450     JSC::JSValue result = smartData->frame->script()->executeScript(WTF::String::fromUTF8(script), true).jsValue();
451
452     if (!smartData->frame) // In case the script removed our frame from the page.
453         return 0;
454
455     if (!result || (!result.isBoolean() && !result.isString() && !result.isNumber()))
456         return 0;
457
458     JSC::ExecState* exec = smartData->frame->script()->globalObject(WebCore::mainThreadNormalWorld())->globalExec();
459     JSC::JSLockHolder lock(exec);
460     resultString = WebCore::ustringToString(result.toString(exec)->value(exec));
461     return eina_stringshare_add(resultString.utf8().data());
462 #else
463     notImplemented();
464     return 0;
465 #endif
466 }
467
468 Eina_Bool ewk_frame_editable_get(const Evas_Object* ewkFrame)
469 {
470     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
471     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
472     return smartData->editable;
473 }
474
475 Eina_Bool ewk_frame_editable_set(Evas_Object* ewkFrame, Eina_Bool editable)
476 {
477     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
478     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
479     editable = !!editable;
480     if (smartData->editable == editable)
481         return true;
482     smartData->editable = editable;
483     if (editable)
484         smartData->frame->editor()->applyEditingStyleToBodyElement();
485     return true;
486 }
487
488 const char* ewk_frame_selection_get(const Evas_Object* ewkFrame)
489 {
490     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, 0);
491     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, 0);
492     WTF::CString selectedText = smartData->frame->editor()->selectedText().utf8();
493     if (selectedText.isNull())
494         return 0;
495     return eina_stringshare_add(selectedText.data());
496 }
497
498 Eina_Bool ewk_frame_text_search(const Evas_Object* ewkFrame, const char* text, Eina_Bool caseSensitive, Eina_Bool forward, Eina_Bool wrap)
499 {
500     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
501     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
502     EINA_SAFETY_ON_NULL_RETURN_VAL(text, false);
503
504     return smartData->frame->editor()->findString(WTF::String::fromUTF8(text), forward, caseSensitive, wrap, true);
505 }
506
507 unsigned int ewk_frame_text_matches_mark(Evas_Object* ewkFrame, const char* string, Eina_Bool caseSensitive, Eina_Bool highlight, unsigned int limit)
508 {
509     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, 0);
510     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, 0);
511     EINA_SAFETY_ON_NULL_RETURN_VAL(string, 0);
512
513     smartData->frame->editor()->setMarkedTextMatchesAreHighlighted(highlight);
514     return smartData->frame->editor()->countMatchesForText(WTF::String::fromUTF8(string), caseSensitive, limit, true);
515 }
516
517 Eina_Bool ewk_frame_text_matches_unmark_all(Evas_Object* ewkFrame)
518 {
519     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
520     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
521
522     smartData->frame->document()->markers()->removeMarkers(WebCore::DocumentMarker::TextMatch);
523     return true;
524 }
525
526 Eina_Bool ewk_frame_text_matches_highlight_set(Evas_Object* ewkFrame, Eina_Bool highlight)
527 {
528     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
529     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
530     smartData->frame->editor()->setMarkedTextMatchesAreHighlighted(highlight);
531     return true;
532 }
533
534 Eina_Bool ewk_frame_text_matches_highlight_get(const Evas_Object* ewkFrame)
535 {
536     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
537     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
538     return smartData->frame->editor()->markedTextMatchesAreHighlighted();
539 }
540
541 /**
542  * Comparison function used by ewk_frame_text_matches_nth_pos_get
543  */
544 static bool _ewk_frame_rect_cmp_less_than(const WebCore::IntRect& begin, const WebCore::IntRect& end)
545 {
546     return (begin.y() < end.y() || (begin.y() == end.y() && begin.x() < end.x()));
547 }
548
549 /**
550  * Predicate used by ewk_frame_text_matches_nth_pos_get
551  */
552 static bool _ewk_frame_rect_is_negative_value(const WebCore::IntRect& rect)
553 {
554     return (rect.x() < 0 || rect.y() < 0);
555 }
556
557 Eina_Bool ewk_frame_text_matches_nth_pos_get(const Evas_Object* ewkFrame, size_t number, int* x, int* y)
558 {
559     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
560     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
561
562     Vector<WebCore::IntRect> intRects = smartData->frame->document()->markers()->renderedRectsForMarkers(WebCore::DocumentMarker::TextMatch);
563
564     /* remove useless values */
565     std::remove_if(intRects.begin(), intRects.end(), _ewk_frame_rect_is_negative_value);
566
567     if (intRects.isEmpty() || number > intRects.size())
568         return false;
569
570     std::sort(intRects.begin(), intRects.end(), _ewk_frame_rect_cmp_less_than);
571
572     if (x)
573         *x = intRects[number - 1].x();
574     if (y)
575         *y = intRects[number - 1].y();
576     return true;
577 }
578
579 Eina_Bool ewk_frame_stop(Evas_Object* ewkFrame)
580 {
581     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
582     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
583     smartData->frame->loader()->stopAllLoaders();
584     return true;
585 }
586
587 Eina_Bool ewk_frame_reload(Evas_Object* ewkFrame)
588 {
589     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
590     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
591     smartData->frame->loader()->reload();
592     return true;
593 }
594
595 Eina_Bool ewk_frame_reload_full(Evas_Object* ewkFrame)
596 {
597     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
598     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
599     smartData->frame->loader()->reload(true);
600     return true;
601 }
602
603 Eina_Bool ewk_frame_back(Evas_Object* ewkFrame)
604 {
605     return ewk_frame_navigate(ewkFrame, -1);
606 }
607
608 Eina_Bool ewk_frame_forward(Evas_Object* ewkFrame)
609 {
610     return ewk_frame_navigate(ewkFrame, 1);
611 }
612
613 Eina_Bool ewk_frame_navigate(Evas_Object* ewkFrame, int steps)
614 {
615     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
616     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
617     WebCore::Page* page = smartData->frame->page();
618     if (!page->canGoBackOrForward(steps))
619         return false;
620     page->goBackOrForward(steps);
621     return true;
622 }
623
624 Eina_Bool ewk_frame_back_possible(Evas_Object* ewkFrame)
625 {
626     return ewk_frame_navigate_possible(ewkFrame, -1);
627 }
628
629 Eina_Bool ewk_frame_forward_possible(Evas_Object* ewkFrame)
630 {
631     return ewk_frame_navigate_possible(ewkFrame, 1);
632 }
633
634 Eina_Bool ewk_frame_navigate_possible(Evas_Object* ewkFrame, int steps)
635 {
636     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
637     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
638     WebCore::Page* page = smartData->frame->page();
639     return page->canGoBackOrForward(steps);
640 }
641
642 float ewk_frame_page_zoom_get(const Evas_Object* ewkFrame)
643 {
644     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, -1.0);
645     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, -1.0);
646     return smartData->frame->pageZoomFactor();
647 }
648
649 Eina_Bool ewk_frame_page_zoom_set(Evas_Object* ewkFrame, float pageZoomFactor)
650 {
651     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
652     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
653     smartData->frame->setPageZoomFactor(pageZoomFactor);
654     return true;
655 }
656
657 float ewk_frame_text_zoom_get(const Evas_Object* ewkFrame)
658 {
659     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, -1.0);
660     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, -1.0);
661     return smartData->frame->textZoomFactor();
662 }
663
664 Eina_Bool ewk_frame_text_zoom_set(Evas_Object* ewkFrame, float textZoomFactor)
665 {
666     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
667     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
668     smartData->frame->setTextZoomFactor(textZoomFactor);
669     return true;
670 }
671
672 void ewk_frame_hit_test_free(Ewk_Hit_Test* hitTest)
673 {
674     EINA_SAFETY_ON_NULL_RETURN(hitTest);
675     eina_stringshare_del(hitTest->title.string);
676     eina_stringshare_del(hitTest->alternate_text);
677     eina_stringshare_del(hitTest->link.text);
678     eina_stringshare_del(hitTest->link.url);
679     eina_stringshare_del(hitTest->link.title);
680     eina_stringshare_del(hitTest->image_uri);
681     eina_stringshare_del(hitTest->media_uri);
682     delete hitTest;
683 }
684
685 Ewk_Hit_Test* ewk_frame_hit_test_new(const Evas_Object* ewkFrame, int x, int y)
686 {
687     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, 0);
688     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, 0);
689
690     WebCore::FrameView* view = smartData->frame->view();
691     EINA_SAFETY_ON_NULL_RETURN_VAL(view, 0);
692     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame->contentRenderer(), 0);
693
694     WebCore::HitTestResult result = smartData->frame->eventHandler()->hitTestResultAtPoint
695                                         (view->windowToContents(WebCore::IntPoint(x, y)),
696                                         /*allowShadowContent*/ false, /*ignoreClipping*/ true);
697
698     if (result.scrollbar())
699         return 0;
700     if (!result.innerNode())
701         return 0;
702
703     Ewk_Hit_Test* hitTest = new Ewk_Hit_Test;
704     hitTest->x = result.point().x();
705     hitTest->y = result.point().y();
706 #if 0
707     // FIXME
708     hitTest->bounding_box.x = result.boundingBox().x();
709     hitTest->bounding_box.y = result.boundingBox().y();
710     hitTest->bounding_box.width = result.boundingBox().width();
711     hitTest->bounding_box.height = result.boundingBox().height();
712 #else
713     hitTest->bounding_box.x = 0;
714     hitTest->bounding_box.y = 0;
715     hitTest->bounding_box.w = 0;
716     hitTest->bounding_box.h = 0;
717 #endif
718
719     WebCore::TextDirection direction;
720     hitTest->title.string = eina_stringshare_add(result.title(direction).utf8().data());
721     hitTest->title.direction = (direction == WebCore::LTR) ? EWK_TEXT_DIRECTION_LEFT_TO_RIGHT : EWK_TEXT_DIRECTION_RIGHT_TO_LEFT;
722     hitTest->alternate_text = eina_stringshare_add(result.altDisplayString().utf8().data());
723     if (result.innerNonSharedNode() && result.innerNonSharedNode()->document()
724         && result.innerNonSharedNode()->document()->frame())
725         hitTest->frame = EWKPrivate::kitFrame(result.innerNonSharedNode()->document()->frame());
726
727     hitTest->link.text = eina_stringshare_add(result.textContent().utf8().data());
728     hitTest->link.url = eina_stringshare_add(result.absoluteLinkURL().string().utf8().data());
729     hitTest->link.title = eina_stringshare_add(result.titleDisplayString().utf8().data());
730     hitTest->link.target_frame = EWKPrivate::kitFrame(result.targetFrame());
731
732     hitTest->image_uri = eina_stringshare_add(result.absoluteImageURL().string().utf8().data());
733     hitTest->media_uri = eina_stringshare_add(result.absoluteMediaURL().string().utf8().data());
734
735     int context = EWK_HIT_TEST_RESULT_CONTEXT_DOCUMENT;
736
737     if (!result.absoluteLinkURL().isEmpty())
738         context |= EWK_HIT_TEST_RESULT_CONTEXT_LINK;
739     if (!result.absoluteImageURL().isEmpty())
740         context |= EWK_HIT_TEST_RESULT_CONTEXT_IMAGE;
741     if (!result.absoluteMediaURL().isEmpty())
742         context |= EWK_HIT_TEST_RESULT_CONTEXT_MEDIA;
743     if (result.isSelected())
744         context |= EWK_HIT_TEST_RESULT_CONTEXT_SELECTION;
745     if (result.isContentEditable())
746         context |= EWK_HIT_TEST_RESULT_CONTEXT_EDITABLE;
747
748     hitTest->context = static_cast<Ewk_Hit_Test_Result_Context>(context);
749
750     return hitTest;
751 }
752
753 void ewk_frame_intent_deliver(const Evas_Object* ewkFrame, Ewk_Intent* ewk_intent)
754 {
755 #if ENABLE(WEB_INTENTS)
756     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData);
757     EINA_SAFETY_ON_NULL_RETURN(smartData->frame);
758
759     WebCore::Intent* intent = EWKPrivate::coreIntent(ewk_intent);
760
761     OwnPtr<WebCore::MessagePortChannelArray> channels;
762     WebCore::MessagePortChannelArray* origChannels = intent->messagePorts();
763     if (origChannels && origChannels->size()) {
764         channels = adoptPtr(new WebCore::MessagePortChannelArray(origChannels->size()));
765         for (size_t i = 0; i < origChannels->size(); ++i)
766             (*channels)[i] = origChannels->at(i).release();
767     }
768     OwnPtr<WebCore::MessagePortArray> ports = WebCore::MessagePort::entanglePorts(*(smartData->frame->domWindow()->scriptExecutionContext()), channels.release());
769
770     OwnPtr<WebCore::DeliveredIntentClient> dummyClient;
771     RefPtr<WebCore::DeliveredIntent> deliveredIntent = WebCore::DeliveredIntent::create(smartData->frame, dummyClient.release(), intent->action(), intent->type(), intent->data(), ports.release(), intent->extras());
772
773     WebCore::DOMWindowIntents::from(smartData->frame->domWindow())->deliver(deliveredIntent.release());
774 #endif
775 }
776
777 Eina_Bool
778 ewk_frame_scroll_add(Evas_Object* ewkFrame, int deltaX, int deltaY)
779 {
780     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
781     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
782     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame->view(), false);
783     smartData->frame->view()->scrollBy(WebCore::IntSize(deltaX, deltaY));
784     return true;
785 }
786
787 Eina_Bool
788 ewk_frame_scroll_set(Evas_Object* ewkFrame, int x, int y)
789 {
790     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
791     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
792     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame->view(), false);
793     smartData->frame->view()->setScrollPosition(WebCore::IntPoint(x, y));
794     return true;
795 }
796
797 Eina_Bool
798 ewk_frame_scroll_size_get(const Evas_Object* ewkFrame, int* width, int* height)
799 {
800     if (width)
801         *width = 0;
802     if (height)
803         *height = 0;
804     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
805     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
806     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame->view(), false);
807     WebCore::IntPoint point = smartData->frame->view()->maximumScrollPosition();
808     if (width)
809         *width = point.x();
810     if (height)
811         *height = point.y();
812     return true;
813 }
814
815 Eina_Bool
816 ewk_frame_scroll_pos_get(const Evas_Object* ewkFrame, int* x, int* y)
817 {
818     if (x)
819         *x = 0;
820     if (y)
821         *y = 0;
822     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
823     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
824     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame->view(), false);
825     WebCore::IntPoint pos = smartData->frame->view()->scrollPosition();
826     if (x)
827         *x = pos.x();
828     if (y)
829         *y = pos.y();
830     return true;
831 }
832
833 Eina_Bool ewk_frame_visible_content_geometry_get(const Evas_Object* ewkFrame, Eina_Bool includeScrollbars, int* x, int* y, int* width, int* height)
834 {
835     if (x)
836         *x = 0;
837     if (y)
838         *y = 0;
839     if (width)
840         *width = 0;
841     if (height)
842         *height = 0;
843     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
844     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
845     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame->view(), false);
846     WebCore::IntRect rect = smartData->frame->view()->visibleContentRect(includeScrollbars);
847     if (x)
848         *x = rect.x();
849     if (y)
850         *y = rect.y();
851     if (width)
852         *width = rect.width();
853     if (height)
854         *height = rect.height();
855     return true;
856 }
857
858 Eina_Bool ewk_frame_paint_full_get(const Evas_Object* ewkFrame)
859 {
860     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
861     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
862     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame->view(), false);
863     return smartData->frame->view()->paintsEntireContents();
864 }
865
866 void ewk_frame_paint_full_set(Evas_Object* ewkFrame, Eina_Bool flag)
867 {
868     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData);
869     EINA_SAFETY_ON_NULL_RETURN(smartData->frame);
870     EINA_SAFETY_ON_NULL_RETURN(smartData->frame->view());
871     smartData->frame->view()->setPaintsEntireContents(flag);
872 }
873
874 Eina_Bool ewk_frame_feed_focus_in(Evas_Object* ewkFrame)
875 {
876     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
877     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
878     WebCore::FocusController* focusController = smartData->frame->page()->focusController();
879     focusController->setFocusedFrame(smartData->frame);
880     return true;
881 }
882
883 Eina_Bool ewk_frame_feed_focus_out(Evas_Object* ewkFrame)
884 {
885     // TODO: what to do on focus out?
886     ERR("what to do?");
887     return false;
888 }
889
890 Eina_Bool ewk_frame_focused_element_geometry_get(const Evas_Object *ewkFrame, int *x, int *y, int *w, int *h)
891 {
892     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
893     WebCore::Document* document = smartData->frame->document();
894     if (!document)
895         return false;
896     WebCore::Node* focusedNode = document->focusedNode();
897     if (!focusedNode)
898         return false;
899     WebCore::IntRect nodeRect = focusedNode->getPixelSnappedRect();
900     if (x)
901         *x = nodeRect.x();
902     if (y)
903         *y = nodeRect.y();
904     if (w)
905         *w = nodeRect.width();
906     if (h)
907         *h = nodeRect.height();
908     return true;
909 }
910
911 Eina_Bool ewk_frame_feed_mouse_wheel(Evas_Object* ewkFrame, const Evas_Event_Mouse_Wheel* wheelEvent)
912 {
913     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
914     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
915     EINA_SAFETY_ON_NULL_RETURN_VAL(wheelEvent, false);
916
917     WebCore::FrameView* view = smartData->frame->view();
918     DBG("ewkFrame=%p, view=%p, direction=%d, z=%d, pos=%d,%d",
919         ewkFrame, view, wheelEvent->direction, wheelEvent->z, wheelEvent->canvas.x, wheelEvent->canvas.y);
920     EINA_SAFETY_ON_NULL_RETURN_VAL(view, false);
921
922     WebCore::PlatformWheelEvent event(wheelEvent);
923     return smartData->frame->eventHandler()->handleWheelEvent(event);
924 }
925
926 Eina_Bool ewk_frame_feed_mouse_down(Evas_Object* ewkFrame, const Evas_Event_Mouse_Down* downEvent)
927 {
928     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
929     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
930     EINA_SAFETY_ON_NULL_RETURN_VAL(downEvent, false);
931
932     WebCore::FrameView* view = smartData->frame->view();
933     DBG("ewkFrame=%p, view=%p, button=%d, pos=%d,%d",
934         ewkFrame, view, downEvent->button, downEvent->canvas.x, downEvent->canvas.y);
935     EINA_SAFETY_ON_NULL_RETURN_VAL(view, false);
936
937     Evas_Coord x, y;
938     evas_object_geometry_get(smartData->view, &x, &y, 0, 0);
939
940     WebCore::PlatformMouseEvent event(downEvent, WebCore::IntPoint(x, y));
941     return smartData->frame->eventHandler()->handleMousePressEvent(event);
942 }
943
944 Eina_Bool ewk_frame_feed_mouse_up(Evas_Object* ewkFrame, const Evas_Event_Mouse_Up* upEvent)
945 {
946     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
947     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
948     EINA_SAFETY_ON_NULL_RETURN_VAL(upEvent, false);
949
950     WebCore::FrameView* view = smartData->frame->view();
951     DBG("ewkFrame=%p, view=%p, button=%d, pos=%d,%d",
952         ewkFrame, view, upEvent->button, upEvent->canvas.x, upEvent->canvas.y);
953     EINA_SAFETY_ON_NULL_RETURN_VAL(view, false);
954
955     Evas_Coord x, y;
956     evas_object_geometry_get(smartData->view, &x, &y, 0, 0);
957
958     WebCore::PlatformMouseEvent event(upEvent, WebCore::IntPoint(x, y));
959     return smartData->frame->eventHandler()->handleMouseReleaseEvent(event);
960 }
961
962 Eina_Bool ewk_frame_feed_mouse_move(Evas_Object* ewkFrame, const Evas_Event_Mouse_Move* moveEvent)
963 {
964     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
965     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
966     EINA_SAFETY_ON_NULL_RETURN_VAL(moveEvent, false);
967
968     WebCore::FrameView* view = smartData->frame->view();
969     DBG("ewkFrame=%p, view=%p, pos: old=%d,%d, new=%d,%d, buttons=%d",
970         ewkFrame, view, moveEvent->cur.canvas.x, moveEvent->cur.canvas.y,
971         moveEvent->prev.canvas.x, moveEvent->prev.canvas.y, moveEvent->buttons);
972     EINA_SAFETY_ON_NULL_RETURN_VAL(view, false);
973
974     Evas_Coord x, y;
975     evas_object_geometry_get(smartData->view, &x, &y, 0, 0);
976
977     WebCore::PlatformMouseEvent event(moveEvent, WebCore::IntPoint(x, y));
978     return smartData->frame->eventHandler()->mouseMoved(event);
979 }
980
981 Eina_Bool ewk_frame_feed_touch_event(Evas_Object* ewkFrame, Ewk_Touch_Event_Type action, Eina_List* points, unsigned modifiers)
982 {
983 #if ENABLE(TOUCH_EVENTS)
984     EINA_SAFETY_ON_NULL_RETURN_VAL(points, false);
985     EWK_FRAME_SD_GET(ewkFrame, smartData);
986
987     if (!smartData || !smartData->frame || !ewk_view_need_touch_events_get(smartData->view))
988         return false;
989
990     Evas_Coord x, y;
991     evas_object_geometry_get(smartData->view, &x, &y, 0, 0);
992
993     WebCore::PlatformEvent::Type type;
994     switch (action) {
995     case EWK_TOUCH_START:
996         type = WebCore::PlatformEvent::TouchStart;
997         break;
998     case EWK_TOUCH_MOVE:
999         type = WebCore::PlatformEvent::TouchMove;
1000         break;
1001     case EWK_TOUCH_END:
1002         type = WebCore::PlatformEvent::TouchEnd;
1003         break;
1004     case EWK_TOUCH_CANCEL:
1005         type = WebCore::PlatformEvent::TouchCancel;
1006         break;
1007     default:
1008         ASSERT_NOT_REACHED();
1009         return false;
1010     }
1011
1012     unsigned touchModifiers = 0;
1013     if (modifiers & ECORE_EVENT_MODIFIER_ALT)
1014         touchModifiers |= WebCore::PlatformEvent::AltKey;
1015     if (modifiers & ECORE_EVENT_MODIFIER_CTRL)
1016         touchModifiers |= WebCore::PlatformEvent::CtrlKey;
1017     if (modifiers & ECORE_EVENT_MODIFIER_SHIFT)
1018         touchModifiers |= WebCore::PlatformEvent::ShiftKey;
1019     if (modifiers & ECORE_EVENT_MODIFIER_WIN)
1020         touchModifiers |= WebCore::PlatformEvent::MetaKey;
1021
1022     WebCore::PlatformTouchEvent touchEvent(points, WebCore::IntPoint(x, y), type, static_cast<WebCore::PlatformEvent::Modifiers>(touchModifiers));
1023     return smartData->frame->eventHandler()->handleTouchEvent(touchEvent);
1024 #else
1025     return false;
1026 #endif
1027 }
1028
1029 static inline Eina_Bool _ewk_frame_handle_key_scrolling(WebCore::Frame* frame, const WebCore::PlatformKeyboardEvent& keyEvent)
1030 {
1031     WebCore::ScrollDirection direction;
1032     WebCore::ScrollGranularity granularity;
1033
1034     int keyCode = keyEvent.windowsVirtualKeyCode();
1035
1036     switch (keyCode) {
1037     case VK_SPACE:
1038         granularity = WebCore::ScrollByPage;
1039         if (keyEvent.shiftKey())
1040             direction = WebCore::ScrollUp;
1041         else
1042             direction = WebCore::ScrollDown;
1043         break;
1044     case VK_NEXT:
1045         granularity = WebCore::ScrollByPage;
1046         direction = WebCore::ScrollDown;
1047         break;
1048     case VK_PRIOR:
1049         granularity = WebCore::ScrollByPage;
1050         direction = WebCore::ScrollUp;
1051         break;
1052     case VK_HOME:
1053         granularity = WebCore::ScrollByDocument;
1054         direction = WebCore::ScrollUp;
1055         break;
1056     case VK_END:
1057         granularity = WebCore::ScrollByDocument;
1058         direction = WebCore::ScrollDown;
1059         break;
1060     case VK_LEFT:
1061         granularity = WebCore::ScrollByLine;
1062         direction = WebCore::ScrollLeft;
1063         break;
1064     case VK_RIGHT:
1065         granularity = WebCore::ScrollByLine;
1066         direction = WebCore::ScrollRight;
1067         break;
1068     case VK_UP:
1069         direction = WebCore::ScrollUp;
1070         if (keyEvent.ctrlKey())
1071             granularity = WebCore::ScrollByDocument;
1072         else
1073             granularity = WebCore::ScrollByLine;
1074         break;
1075     case VK_DOWN:
1076         direction = WebCore::ScrollDown;
1077         if (keyEvent.ctrlKey())
1078             granularity = WebCore::ScrollByDocument;
1079         else
1080             granularity = WebCore::ScrollByLine;
1081         break;
1082     default:
1083         return false;
1084     }
1085
1086     if (frame->eventHandler()->scrollOverflow(direction, granularity))
1087         return false;
1088
1089     frame->view()->scroll(direction, granularity);
1090     return true;
1091 }
1092
1093 Eina_Bool ewk_frame_feed_key_down(Evas_Object* ewkFrame, const Evas_Event_Key_Down* downEvent)
1094 {
1095     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
1096     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
1097     EINA_SAFETY_ON_NULL_RETURN_VAL(downEvent, false);
1098
1099     DBG("ewkFrame=%p keyname=%s (key=%s, string=%s)",
1100         ewkFrame, downEvent->keyname, downEvent->key ? downEvent->key : "", downEvent->string ? downEvent->string : "");
1101
1102     WebCore::PlatformKeyboardEvent event(downEvent);
1103     if (smartData->frame->eventHandler()->keyEvent(event))
1104         return true;
1105
1106     return _ewk_frame_handle_key_scrolling(smartData->frame, event);
1107 }
1108
1109 Eina_Bool ewk_frame_feed_key_up(Evas_Object* ewkFrame, const Evas_Event_Key_Up* upEvent)
1110 {
1111     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
1112     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
1113     EINA_SAFETY_ON_NULL_RETURN_VAL(upEvent, false);
1114
1115     DBG("ewkFrame=%p keyname=%s (key=%s, string=%s)",
1116         ewkFrame, upEvent->keyname, upEvent->key ? upEvent->key : "", upEvent->string ? upEvent->string : "");
1117
1118     WebCore::PlatformKeyboardEvent event(upEvent);
1119     return smartData->frame->eventHandler()->keyEvent(event);
1120 }
1121
1122 Ewk_Text_Selection_Type ewk_frame_text_selection_type_get(const Evas_Object* ewkFrame)
1123 {
1124     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, EWK_TEXT_SELECTION_NONE);
1125     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, EWK_TEXT_SELECTION_NONE);
1126
1127     WebCore::FrameSelection* controller = smartData->frame->selection();
1128     if (!controller)
1129         return EWK_TEXT_SELECTION_NONE;
1130
1131     return static_cast<Ewk_Text_Selection_Type>(controller->selectionType());
1132 }
1133
1134 /* internal methods ****************************************************/
1135
1136 /**
1137  * @internal
1138  *
1139  * Creates a new EFL WebKit Frame object.
1140  *
1141  * Frames are low level entries contained in a page that is contained
1142  * by a view. Usually one operates on the view and not directly on the
1143  * frame.
1144  *
1145  * @param canvas canvas where to create the frame object
1146  *
1147  * @return a new frame object or @c 0 on failure
1148  */
1149 Evas_Object* ewk_frame_add(Evas* canvas)
1150 {
1151     return evas_object_smart_add(canvas, _ewk_frame_smart_class_new());
1152 }
1153
1154 /**
1155  * @internal
1156  *
1157  * Initialize frame based on actual WebKit frame.
1158  *
1159  * This is internal and should never be called by external users.
1160  */
1161 bool ewk_frame_init(Evas_Object* ewkFrame, Evas_Object* view, WebCore::Frame* frame)
1162 {
1163     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
1164     if (!smartData->frame) {
1165         WebCore::FrameLoaderClientEfl* frameLoaderClient = _ewk_frame_loader_efl_get(frame);
1166         frameLoaderClient->setWebFrame(ewkFrame);
1167         smartData->frame = frame;
1168         smartData->view = view;
1169         frame->init();
1170         return true;
1171     }
1172
1173     ERR("frame %p already set for %p, ignored new %p",
1174         smartData->frame, ewkFrame, frame);
1175     return false;
1176 }
1177
1178 /**
1179  * @internal
1180  *
1181  * Adds child to the frame.
1182  */
1183 bool ewk_frame_child_add(Evas_Object* ewkFrame, WTF::PassRefPtr<WebCore::Frame> child, const WTF::String& name, const WebCore::KURL& url, const WTF::String& referrer)
1184 {
1185     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, 0);
1186     char buffer[256];
1187     Evas_Object* frame;
1188     WebCore::Frame* coreFrame;
1189
1190     frame = ewk_frame_add(smartData->base.evas);
1191     if (!frame) {
1192         ERR("Could not create ewk_frame object.");
1193         return false;
1194     }
1195
1196     coreFrame = child.get();
1197     if (coreFrame->tree())
1198         coreFrame->tree()->setName(name);
1199     else
1200         ERR("no tree for child object");
1201     smartData->frame->tree()->appendChild(child);
1202
1203     if (!ewk_frame_init(frame, smartData->view, coreFrame)) {
1204         evas_object_del(frame);
1205         return false;
1206     }
1207     snprintf(buffer, sizeof(buffer), "EWK_Frame:child/%s", name.utf8().data());
1208     evas_object_name_set(frame, buffer);
1209     evas_object_smart_member_add(frame, ewkFrame);
1210     evas_object_show(frame);
1211
1212     // The creation of the frame may have run arbitrary JavaScript that removed it from the page already.
1213     if (!coreFrame->page()) {
1214         evas_object_del(frame);
1215         return true;
1216     }
1217
1218     evas_object_smart_callback_call(smartData->view, "frame,created", frame);
1219     smartData->frame->loader()->loadURLIntoChildFrame(url, referrer, coreFrame);
1220
1221     // The frame's onload handler may have removed it from the document.
1222     // See fast/dom/null-page-show-modal-dialog-crash.html for an example.
1223     if (!coreFrame->tree()->parent()) {
1224         evas_object_del(frame);
1225         return true;
1226     }
1227
1228     return true;
1229 }
1230
1231 /**
1232  * @internal
1233  * Change the ewk view this frame is associated with.
1234  *
1235  * @param ewkFrame The ewk frame to act upon.
1236  * @param newParent The new view that will be set as the parent of the frame.
1237  */
1238 void ewk_frame_view_set(Evas_Object* ewkFrame, Evas_Object* newParent)
1239 {
1240     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData);
1241
1242     evas_object_smart_member_del(ewkFrame);
1243     evas_object_smart_member_add(ewkFrame, newParent);
1244
1245     smartData->view = newParent;
1246 }
1247
1248 /**
1249  * @internal
1250  * Frame was destroyed by loader, remove internal reference.
1251  */
1252 void ewk_frame_core_gone(Evas_Object* ewkFrame)
1253 {
1254     DBG("ewkFrame=%p", ewkFrame);
1255     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData);
1256     smartData->frame = 0;
1257 }
1258
1259 /**
1260  * @internal
1261  * Reports cancellation of a client redirect.
1262  *
1263  * @param ewkFrame Frame.
1264  *
1265  * Emits signal: "redirect,cancelled"
1266  */
1267 void ewk_frame_redirect_cancelled(Evas_Object* ewkFrame)
1268 {
1269     evas_object_smart_callback_call(ewkFrame, "redirect,cancelled", 0);
1270 }
1271
1272 /**
1273  * @internal
1274  * Reports receipt of server redirect for provisional load.
1275  *
1276  * @param ewkFrame Frame.
1277  *
1278  * Emits signal: "redirect,load,provisional"
1279  */
1280 void ewk_frame_redirect_provisional_load(Evas_Object* ewkFrame)
1281 {
1282     evas_object_smart_callback_call(ewkFrame, "redirect,load,provisional", 0);
1283 }
1284
1285 /**
1286  * @internal
1287  * Reports that a client redirect will be performed.
1288  *
1289  * @param ewkFrame Frame.
1290  * @param url Redirection URL.
1291  *
1292  * Emits signal: "redirect,requested"
1293  */
1294 void ewk_frame_redirect_requested(Evas_Object* ewkFrame, const char* url)
1295 {
1296     evas_object_smart_callback_call(ewkFrame, "redirect,requested", (void*)url);
1297 }
1298
1299 /**
1300  * @internal
1301  * Reports a resource will be requested. User may override behavior of webkit by
1302  * changing values in @param request.
1303  *
1304  * @param ewkFrame Frame.
1305  * @param messages Messages containing the request details that user may override and a
1306  * possible redirect reponse. Whenever values on this struct changes, it must be properly
1307  * malloc'd as it will be freed afterwards.
1308  *
1309  * Emits signal: "resource,request,willsend"
1310  */
1311 void ewk_frame_request_will_send(Evas_Object* ewkFrame, Ewk_Frame_Resource_Messages* messages)
1312 {
1313     evas_object_smart_callback_call(ewkFrame, "resource,request,willsend", messages);
1314 }
1315
1316 /**
1317  * @internal
1318  * Reports that there's a new resource.
1319  *
1320  * @param ewkFrame Frame.
1321  * @param request New request details. No changes are allowed to fields.
1322  *
1323  * Emits signal: "resource,request,new"
1324  */
1325 void ewk_frame_request_assign_identifier(Evas_Object* ewkFrame, const Ewk_Frame_Resource_Request* request)
1326 {
1327     evas_object_smart_callback_call(ewkFrame, "resource,request,new", (void*)request);
1328 }
1329
1330 /**
1331  * @internal
1332  * Reports that a response to a resource request was received.
1333  *
1334  * @param ewkFrame Frame.
1335  * @param request Response details. No changes are allowed to fields.
1336  *
1337  * Emits signal: "resource,response,received"
1338  */
1339 void ewk_frame_response_received(Evas_Object* ewkFrame, Ewk_Frame_Resource_Response* response)
1340 {
1341     evas_object_smart_callback_call(ewkFrame, "resource,response,received", response);
1342 }
1343
1344 /**
1345  * @internal
1346  * Reports that first navigation occurred
1347  *
1348  * @param ewkFrame Frame.
1349  *
1350  * Emits signal: "navigation,first"
1351  */
1352 void ewk_frame_did_perform_first_navigation(Evas_Object* ewkFrame)
1353 {
1354     evas_object_smart_callback_call(ewkFrame, "navigation,first", 0);
1355 }
1356
1357 /**
1358  * @internal
1359  * Reports frame will be saved to current state
1360  *
1361  * @param ewkFrame Frame.
1362  * @param item History item to save details to.
1363  *
1364  * Emits signal: "state,save"
1365  */
1366 void ewk_frame_view_state_save(Evas_Object* ewkFrame, WebCore::HistoryItem* item)
1367 {
1368     evas_object_smart_callback_call(ewkFrame, "state,save", 0);
1369 }
1370
1371 /**
1372  * @internal
1373  * Reports the frame committed load.
1374  *
1375  * Emits signal: "load,committed" with no parameters.
1376  */
1377 void ewk_frame_load_committed(Evas_Object* ewkFrame)
1378 {
1379     evas_object_smart_callback_call(ewkFrame, "load,committed", 0);
1380 }
1381
1382 /**
1383  * @internal
1384  * Reports the frame started loading something.
1385  *
1386  * Emits signal: "load,started" with no parameters.
1387  */
1388 void ewk_frame_load_started(Evas_Object* ewkFrame)
1389 {
1390     Evas_Object* mainFrame;
1391     DBG("ewkFrame=%p", ewkFrame);
1392     evas_object_smart_callback_call(ewkFrame, "load,started", 0);
1393     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData);
1394     ewk_view_load_started(smartData->view, ewkFrame);
1395
1396     mainFrame = ewk_view_frame_main_get(smartData->view);
1397     if (mainFrame == ewkFrame)
1398         ewk_view_frame_main_load_started(smartData->view);
1399 }
1400
1401 /**
1402  * @internal
1403  * Reports the frame started provisional load.
1404  *
1405  * @param ewkFrame Frame.
1406  *
1407  * Emits signal: "load,provisional" with no parameters.
1408  */
1409 void ewk_frame_load_provisional(Evas_Object* ewkFrame)
1410 {
1411     evas_object_smart_callback_call(ewkFrame, "load,provisional", 0);
1412 }
1413
1414 /**
1415  * @internal
1416  * Reports the frame provisional load failed.
1417  *
1418  * @param ewkFrame Frame.
1419  * @param error Load error.
1420  *
1421  * Emits signal: "load,provisional,failed" with pointer to Ewk_Frame_Load_Error.
1422  */
1423 void ewk_frame_load_provisional_failed(Evas_Object* ewkFrame, const Ewk_Frame_Load_Error* error)
1424 {
1425     evas_object_smart_callback_call(ewkFrame, "load,provisional,failed", const_cast<Ewk_Frame_Load_Error*>(error));
1426 }
1427
1428 /**
1429  * @internal
1430  * Reports the frame finished first layout.
1431  *
1432  * @param ewkFrame Frame.
1433  *
1434  * Emits signal: "load,firstlayout,finished" with no parameters.
1435  */
1436 void ewk_frame_load_firstlayout_finished(Evas_Object* ewkFrame)
1437 {
1438     evas_object_smart_callback_call(ewkFrame, "load,firstlayout,finished", 0);
1439 }
1440
1441 /**
1442  * @internal
1443  * Reports the frame finished first non empty layout.
1444  *
1445  * @param ewkFrame Frame.
1446  *
1447  * Emits signal: "load,nonemptylayout,finished" with no parameters.
1448  */
1449 void ewk_frame_load_firstlayout_nonempty_finished(Evas_Object* ewkFrame)
1450 {
1451     evas_object_smart_callback_call(ewkFrame, "load,nonemptylayout,finished", 0);
1452 }
1453
1454 /**
1455  * @internal
1456  * Reports the loading of a document has finished on frame.
1457  *
1458  * @param ewkFrame Frame.
1459  *
1460  * Emits signal: "load,document,finished" with no parameters.
1461  */
1462 void ewk_frame_load_document_finished(Evas_Object* ewkFrame)
1463 {
1464     evas_object_smart_callback_call(ewkFrame, "load,document,finished", 0);
1465     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData);
1466     ewk_view_load_document_finished(smartData->view, ewkFrame);
1467 }
1468
1469 /**
1470  * @internal
1471  * Reports load finished, optionally with error information.
1472  *
1473  * Emits signal: "load,finished" with pointer to Ewk_Frame_Load_Error
1474  * if any error, or @c NULL if successful load.
1475  *
1476  * @note there should notbe any error stuff here, but trying to be
1477  *       compatible with previous WebKit.
1478  */
1479 void ewk_frame_load_finished(Evas_Object* ewkFrame, const char* errorDomain, int errorCode, bool isCancellation, const char* errorDescription, const char* failingUrl)
1480 {
1481     Ewk_Frame_Load_Error buffer, *error;
1482     if (!errorDomain) {
1483         DBG("ewkFrame=%p, success.", ewkFrame);
1484         error = 0;
1485     } else {
1486         DBG("ewkFrame=%p, error=%s (%d, cancellation=%hhu) \"%s\", url=%s",
1487             ewkFrame, errorDomain, errorCode, isCancellation,
1488             errorDescription, failingUrl);
1489
1490         buffer.domain = errorDomain;
1491         buffer.code = errorCode;
1492         buffer.is_cancellation = isCancellation;
1493         buffer.description = errorDescription;
1494         buffer.failing_url = failingUrl;
1495         buffer.resource_identifier = 0;
1496         buffer.frame = ewkFrame;
1497         error = &buffer;
1498     }
1499     evas_object_smart_callback_call(ewkFrame, "load,finished", error);
1500     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData);
1501     ewk_view_load_finished(smartData->view, error);
1502 }
1503
1504 /**
1505  * @internal
1506  * Reports resource load finished.
1507  *
1508  * Emits signal: "load,resource,finished" with the resource
1509  * request identifier.
1510  */
1511 void ewk_frame_load_resource_finished(Evas_Object* ewkFrame, unsigned long identifier)
1512 {
1513     evas_object_smart_callback_call(ewkFrame, "load,resource,finished", &identifier);
1514 }
1515
1516 /**
1517  * @internal
1518  * Reports resource load failure, with error information.
1519  *
1520  * Emits signal: "load,resource,failed" with the error information.
1521  */
1522 void ewk_frame_load_resource_failed(Evas_Object* ewkFrame, Ewk_Frame_Load_Error* error)
1523 {
1524     evas_object_smart_callback_call(ewkFrame, "load,resource,failed", error);
1525 }
1526
1527 /**
1528  * @internal
1529  * Reports load failed with error information.
1530  *
1531  * Emits signal: "load,error" with pointer to Ewk_Frame_Load_Error.
1532  */
1533 void ewk_frame_load_error(Evas_Object* ewkFrame, const char* errorDomain, int errorCode, bool isCancellation, const char* errorDescription, const char* failingUrl)
1534 {
1535     Ewk_Frame_Load_Error error;
1536
1537     DBG("ewkFrame=%p, error=%s (%d, cancellation=%hhu) \"%s\", url=%s",
1538         ewkFrame, errorDomain, errorCode, isCancellation,
1539         errorDescription, failingUrl);
1540
1541     EINA_SAFETY_ON_NULL_RETURN(errorDomain);
1542
1543     error.code = errorCode;
1544     error.is_cancellation = isCancellation;
1545     error.domain = errorDomain;
1546     error.description = errorDescription;
1547     error.failing_url = failingUrl;
1548     error.resource_identifier = 0;
1549     error.frame = ewkFrame;
1550     evas_object_smart_callback_call(ewkFrame, "load,error", &error);
1551     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData);
1552     ewk_view_load_error(smartData->view, &error);
1553 }
1554
1555 /**
1556  * @internal
1557  * Reports load progress changed.
1558  *
1559  * Emits signal: "load,progress" with pointer to a double from 0.0 to 1.0.
1560  */
1561 void ewk_frame_load_progress_changed(Evas_Object* ewkFrame)
1562 {
1563     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData);
1564     EINA_SAFETY_ON_NULL_RETURN(smartData->frame);
1565
1566     // TODO: this is per page, there should be a way to have per-frame.
1567     double progress = smartData->frame->page()->progress()->estimatedProgress();
1568
1569     DBG("ewkFrame=%p (p=%0.3f)", ewkFrame, progress);
1570
1571     evas_object_smart_callback_call(ewkFrame, "load,progress", &progress);
1572     ewk_view_load_progress_changed(smartData->view);
1573 }
1574
1575 /**
1576  * @internal
1577  * Reports new intent.
1578  *
1579  * Emits signal: "intent,new" with pointer to a Ewk_Intent_Request.
1580  */
1581 void ewk_frame_intent_new(Evas_Object* ewkFrame, Ewk_Intent_Request* request)
1582 {
1583 #if ENABLE(WEB_INTENTS)
1584     evas_object_smart_callback_call(ewkFrame, "intent,new", request);
1585 #endif
1586 }
1587
1588 /**
1589  * @internal
1590  * Reports an intent service registration.
1591  *
1592  * Emits signal: "intent,service,register" with pointer to a Ewk_Intent_Service_Info.
1593  */
1594 void ewk_frame_intent_service_register(Evas_Object* ewkFrame, Ewk_Intent_Service_Info* info)
1595 {
1596 #if ENABLE(WEB_INTENTS_TAG)
1597     evas_object_smart_callback_call(ewkFrame, "intent,service,register", info);
1598 #endif
1599 }
1600
1601 /**
1602  * @internal
1603  *
1604  * Reports contents size changed.
1605  */
1606 void ewk_frame_contents_size_changed(Evas_Object* ewkFrame, Evas_Coord width, Evas_Coord height)
1607 {
1608     Evas_Coord size[2] = {width, height};
1609     evas_object_smart_callback_call(ewkFrame, "contents,size,changed", size);
1610 }
1611
1612 /**
1613  * @internal
1614  *
1615  * Reports title changed.
1616  */
1617 void ewk_frame_title_set(Evas_Object* ewkFrame, const Ewk_Text_With_Direction* title)
1618 {
1619     DBG("ewkFrame=%p, title=%s, direction=%s", ewkFrame, title->string ? title->string : "(null)", title->direction == EWK_TEXT_DIRECTION_LEFT_TO_RIGHT ? "ltr" : "rtl");
1620     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData);
1621     if (!eina_stringshare_replace(&smartData->title.string, title->string) && (smartData->title.direction == title->direction))
1622         return;
1623     smartData->title.direction = title->direction;
1624     evas_object_smart_callback_call(ewkFrame, "title,changed", (void*)title);
1625 }
1626
1627 /**
1628  * @internal
1629  *
1630  * Creates a view.
1631  */
1632 void ewk_frame_view_create_for_view(Evas_Object* ewkFrame, Evas_Object* view)
1633 {
1634     DBG("ewkFrame=%p, view=%p", ewkFrame, view);
1635     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData);
1636     EINA_SAFETY_ON_NULL_RETURN(smartData->frame);
1637     Evas_Coord width, height;
1638
1639     evas_object_geometry_get(view, 0, 0, &width, &height);
1640
1641     WebCore::IntSize size(width, height);
1642     int red, green, blue, alpha;
1643     WebCore::Color background;
1644
1645     ewk_view_bg_color_get(view, &red, &green, &blue, &alpha);
1646     if (!alpha)
1647         background = WebCore::Color(0, 0, 0, 0);
1648     else if (alpha == 255)
1649         background = WebCore::Color(red, green, blue, alpha);
1650     else
1651         background = WebCore::Color(red * 255 / alpha, green * 255 / alpha, blue * 255 / alpha, alpha);
1652
1653     smartData->frame->createView(size, background, !alpha);
1654     if (!smartData->frame->view())
1655         return;
1656
1657     smartData->frame->view()->setEvasObject(ewkFrame);
1658
1659     ewk_frame_mixed_content_displayed_set(ewkFrame, false);
1660     ewk_frame_mixed_content_run_set(ewkFrame, false);
1661 }
1662
1663 ssize_t ewk_frame_source_get(const Evas_Object* ewkFrame, char** frameSource)
1664 {
1665     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, -1);
1666     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, -1);
1667     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame->document(), -1);
1668     EINA_SAFETY_ON_NULL_RETURN_VAL(frameSource, -1);
1669
1670     WTF::String source;
1671     *frameSource = 0; // Saves 0 to pointer until it's not allocated.
1672
1673     if (!smartData->frame->document()->isHTMLDocument()) {
1674         // FIXME: Support others documents.
1675         WRN("Only HTML documents are supported");
1676         return -1;
1677     }
1678
1679     // Look for <html> tag. If it exists, the node contatins all document's source.
1680     WebCore::Node* documentNode = smartData->frame->document()->documentElement();
1681     if (documentNode)
1682         for (WebCore::Node* node = documentNode->firstChild(); node; node = node->parentElement()) {
1683             if (node->hasTagName(WebCore::HTMLNames::htmlTag)) {
1684                 WebCore::HTMLElement* element = static_cast<WebCore::HTMLElement*>(node);
1685                 if (element)
1686                     source = element->outerHTML();
1687                 break;
1688             }
1689         }
1690
1691     // Try to get <head> and <body> tags if <html> tag was not found.
1692     if (source.isEmpty()) {
1693         if (smartData->frame->document()->head())
1694             source = smartData->frame->document()->head()->outerHTML();
1695
1696         if (smartData->frame->document()->body())
1697             source += smartData->frame->document()->body()->outerHTML();
1698     }
1699
1700     size_t sourceLength = strlen(source.utf8().data());
1701     *frameSource = static_cast<char*>(malloc(sourceLength + 1));
1702     if (!*frameSource) {
1703         CRITICAL("Could not allocate memory.");
1704         return -1;
1705     }
1706
1707     strncpy(*frameSource, source.utf8().data(), sourceLength);
1708     (*frameSource)[sourceLength] = '\0';
1709
1710     return sourceLength;
1711 }
1712
1713 Eina_List* ewk_frame_resources_location_get(const Evas_Object* ewkFrame)
1714 {
1715     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, 0);
1716     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, 0);
1717     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame->document(), 0);
1718
1719     Eina_List* listOfImagesLocation = 0;
1720
1721     // Get src attibute of images and saves them to the Eina_List.
1722     RefPtr<WebCore::HTMLCollection> images = smartData->frame->document()->images();
1723     for (size_t index = 0; index < images->length(); ++index) {
1724         WebCore::HTMLImageElement* imageElement = static_cast<WebCore::HTMLImageElement*>(images->item(index));
1725         if (!imageElement || imageElement->src().isNull() || imageElement->src().isEmpty())
1726             continue;
1727
1728         WTF::String imageLocation = WebCore::decodeURLEscapeSequences(imageElement->src().string());
1729         // Look for duplicated location.
1730         Eina_List* listIterator = 0;
1731         void* data = 0;
1732         Eina_Bool found = false;
1733         EINA_LIST_FOREACH(listOfImagesLocation, listIterator, data)
1734             if (found = !strcmp(static_cast<char*>(data), imageLocation.utf8().data()))
1735                 break;
1736         if (found)
1737             continue;
1738
1739         const char* imageLocationCopy = eina_stringshare_add(imageLocation.utf8().data());
1740         if (!imageLocationCopy)
1741             goto out_of_memory_handler;
1742         listOfImagesLocation = eina_list_append(listOfImagesLocation, imageLocationCopy);
1743         if (eina_error_get())
1744             goto out_of_memory_handler;
1745     }
1746     // FIXME: Get URL others resources (plugins, css, media files).
1747     return listOfImagesLocation;
1748
1749 out_of_memory_handler:
1750     CRITICAL("Could not allocate memory.");
1751     void* data;
1752     EINA_LIST_FREE(listOfImagesLocation, data)
1753         free(data);
1754     return 0;
1755 }
1756
1757 const char* ewk_frame_plain_text_get(const Evas_Object* ewkFrame)
1758 {
1759     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, 0);
1760     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, 0);
1761
1762     if (!smartData->frame->document())
1763         return 0;
1764
1765     WebCore::Element* documentElement = smartData->frame->document()->documentElement();
1766
1767     if (!documentElement)
1768         return 0;
1769
1770     return eina_stringshare_add(documentElement->innerText().utf8().data());
1771 }
1772
1773 Eina_Bool ewk_frame_mixed_content_displayed_get(const Evas_Object* ewkFrame)
1774 {
1775     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
1776     return smartData->hasDisplayedMixedContent;
1777 }
1778
1779 Eina_Bool ewk_frame_mixed_content_run_get(const Evas_Object* ewkFrame)
1780 {
1781     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
1782     return smartData->hasRunMixedContent;
1783 }
1784
1785 Ewk_Certificate_Status ewk_frame_certificate_status_get(Evas_Object* ewkFrame)
1786 {
1787     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, EWK_CERTIFICATE_STATUS_NO_CERTIFICATE);
1788     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, EWK_CERTIFICATE_STATUS_NO_CERTIFICATE);
1789
1790     const WebCore::FrameLoader* frameLoader = smartData->frame->loader();
1791     const WebCore::DocumentLoader* documentLoader = frameLoader->documentLoader();
1792     const WebCore::KURL documentURL = documentLoader->requestURL();
1793
1794     if (!documentURL.protocolIs("https"))
1795         return EWK_CERTIFICATE_STATUS_NO_CERTIFICATE;
1796
1797     if (frameLoader->subframeIsLoading())
1798         return EWK_CERTIFICATE_STATUS_NO_CERTIFICATE;
1799
1800     SoupMessage* soupMessage = documentLoader->request().toSoupMessage();
1801
1802     if (soupMessage && (soup_message_get_flags(soupMessage) & SOUP_MESSAGE_CERTIFICATE_TRUSTED))
1803         return EWK_CERTIFICATE_STATUS_TRUSTED;
1804
1805     return EWK_CERTIFICATE_STATUS_UNTRUSTED;
1806 }
1807
1808 /**
1809  * @internal
1810  * Reports frame favicon changed.
1811  *
1812  * @param ewkFrame Frame.
1813  *
1814  * Emits signal: "icon,changed" with no parameters.
1815  */
1816 void ewk_frame_icon_changed(Evas_Object* ewkFrame)
1817 {
1818     DBG("ewkFrame=%p", ewkFrame);
1819     evas_object_smart_callback_call(ewkFrame, "icon,changed", 0);
1820 }
1821
1822 /**
1823  * @internal
1824  * Reports uri changed and swap internal string reference.
1825  *
1826  * Emits signal: "uri,changed" with new uri as parameter.
1827  */
1828 bool ewk_frame_uri_changed(Evas_Object* ewkFrame)
1829 {
1830     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, false);
1831     EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, false);
1832     WTF::CString uri(smartData->frame->document()->url().string().utf8());
1833
1834     INF("uri=%s", uri.data());
1835     if (!uri.data()) {
1836         ERR("no uri");
1837         return false;
1838     }
1839
1840     eina_stringshare_replace(&smartData->uri, uri.data());
1841     evas_object_smart_callback_call(ewkFrame, "uri,changed", (void*)smartData->uri);
1842     return true;
1843 }
1844
1845 /**
1846  * @internal
1847  *
1848  * Forces layout for frame.
1849  */
1850 void ewk_frame_force_layout(Evas_Object* ewkFrame)
1851 {
1852     DBG("ewkFrame=%p", ewkFrame);
1853     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData);
1854     EINA_SAFETY_ON_NULL_RETURN(smartData->frame);
1855     WebCore::FrameView* view = smartData->frame->view();
1856     if (view)
1857         view->forceLayout(true);
1858 }
1859
1860 /**
1861  * @internal
1862  *
1863  * Creates plugin.
1864  */
1865 WTF::PassRefPtr<WebCore::Widget> ewk_frame_plugin_create(Evas_Object* ewkFrame, const WebCore::IntSize& pluginSize, WebCore::HTMLPlugInElement* element, const WebCore::KURL& url, const WTF::Vector<WTF::String>& paramNames, const WTF::Vector<WTF::String>& paramValues, const WTF::String& mimeType, bool loadManually)
1866 {
1867 #if ENABLE(NETSCAPE_PLUGIN_API)
1868     DBG("ewkFrame=%p, size=%dx%d, element=%p, url=%s, mimeType=%s",
1869         ewkFrame, pluginSize.width(), pluginSize.height(), element,
1870         url.string().utf8().data(), mimeType.utf8().data());
1871
1872     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, sd, 0);
1873
1874     // TODO: emit signal and ask webkit users if something else should be done.
1875     // like creating another x window (see gtk, it allows users to create
1876     // GtkPluginWidget.
1877
1878     WTF::RefPtr<WebCore::PluginView> pluginView = WebCore::PluginView::create
1879         (sd->frame, pluginSize, element, url, paramNames, paramValues,
1880         mimeType, loadManually);
1881
1882     if (pluginView->status() == WebCore::PluginStatusLoadedSuccessfully)
1883         return pluginView.release();
1884 #endif // #if ENABLE(NETSCAPE_PLUGIN_API)
1885     return 0;
1886 }
1887
1888 /**
1889  * @internal
1890  * Reports that editor client selection was changed.
1891  *
1892  * @param ewkFrame Frame
1893  *
1894  * Emits signal: "editorclientselection,changed" with no parameters.
1895  */
1896 void ewk_frame_editor_client_selection_changed(Evas_Object* ewkFrame)
1897 {
1898     evas_object_smart_callback_call(ewkFrame, "editorclient,selection,changed", 0);
1899     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData);
1900     ewk_view_editor_client_selection_changed(smartData->view);
1901 }
1902
1903 /**
1904  * @internal
1905  * Reports that editor client's contents were changed.
1906  *
1907  * @param o Frame
1908  *
1909  * Emits signal: "editorclient,contents,changed" with no parameters.
1910  */
1911 void ewk_frame_editor_client_contents_changed(Evas_Object* ewkFrame)
1912 {
1913     evas_object_smart_callback_call(ewkFrame, "editorclient,contents,changed", 0);
1914     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData);
1915     ewk_view_editor_client_contents_changed(smartData->view);
1916 }
1917
1918 /**
1919  * @internal
1920  * Defines whether the frame has displayed mixed content.
1921  *
1922  * When a frame has displayed mixed content, the currently loaded URI is secure (HTTPS) but it has
1923  * loaded and displayed a resource, such as an image, from an insecure (HTTP) source.
1924  *
1925  * @param hasDisplayed Do or do not clear the flag from the frame. If @c true, the container view
1926  *                     is also notified and it then emits the "mixedcontent,displayed" signal.
1927  *
1928  * Emits signal: "mixedcontent,displayed" with no parameters when @p hasDisplayed is @c true.
1929  */
1930 void ewk_frame_mixed_content_displayed_set(Evas_Object* ewkFrame, bool hasDisplayed)
1931 {
1932     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData);
1933     smartData->hasDisplayedMixedContent = hasDisplayed;
1934
1935     if (hasDisplayed) {
1936         ewk_view_mixed_content_displayed_set(smartData->view, true);
1937         evas_object_smart_callback_call(ewkFrame, "mixedcontent,displayed", 0);
1938     }
1939 }
1940
1941 /**
1942  * @internal
1943  * Defines whether the frame has run mixed content.
1944  *
1945  * When a frame has run mixed content, the currently loaded URI is secure (HTTPS) but it has
1946  * loaded and run a resource, such as a script, from an insecure (HTTP) source.
1947  *
1948  * @param hasDisplayed Do or do not clear the flag from the frame. If @c true, the container view
1949  *                     is also notified and it then emits the "mixedcontent,run" signal.
1950  *
1951  * Emits signal: "mixedcontent,run" with no parameters when @p hasRun is @c true.
1952  */
1953 void ewk_frame_mixed_content_run_set(Evas_Object* ewkFrame, bool hasRun)
1954 {
1955     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData);
1956     smartData->hasRunMixedContent = hasRun;
1957
1958     if (hasRun) {
1959         ewk_view_mixed_content_run_set(smartData->view, true);
1960         evas_object_smart_callback_call(ewkFrame, "mixedcontent,run", 0);
1961     }
1962 }
1963
1964 /**
1965  * @internal
1966  * Reports that reflected XSS is encountered in the page and suppressed.
1967  *
1968  * @param xssInfo Information received from the XSSAuditor when XSS is 
1969  * encountered in the page. 
1970  *
1971  * Emits signal: "xss,detected" with pointer to Ewk_Frame_Xss_Notification.
1972  */
1973 void ewk_frame_xss_detected(Evas_Object* ewkFrame, const Ewk_Frame_Xss_Notification* xssInfo)
1974 {
1975     evas_object_smart_callback_call(ewkFrame, "xss,detected", (void*)xssInfo);
1976 }
1977
1978 namespace EWKPrivate {
1979
1980 WebCore::Frame* coreFrame(const Evas_Object* ewkFrame)
1981 {
1982     EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, 0);
1983     return smartData->frame;
1984 }
1985
1986 Evas_Object* kitFrame(const WebCore::Frame* coreFrame)
1987 {
1988     if (!coreFrame)
1989         return 0;
1990
1991     WebCore::FrameLoaderClientEfl* frameLoaderClient = _ewk_frame_loader_efl_get(coreFrame);
1992     if (!frameLoaderClient)
1993         return 0;
1994
1995     return frameLoaderClient->webFrame();
1996 }
1997
1998 } // namespace EWKPrivate