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