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