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
75static const char EWK_FRAME_TYPE_STR[] = "EWK_Frame";
76
77struct 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
93struct 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
126static Evas_Smart_Class _parent_sc = EVAS_SMART_CLASS_INIT_NULL;
127
128#ifdef EWK_FRAME_DEBUG
129static 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
154static WebCore::FrameLoaderClientEfl* _ewk_frame_loader_efl_get(const WebCore::Frame* frame)
155{
156    return static_cast<WebCore::FrameLoaderClientEfl*>(frame->loader()->client());
157}
158
159static 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
175static Evas_Object* _ewk_frame_children_iterator_get_container(Eina_Iterator_Ewk_Frame* iterator)
176{
177    return iterator->object;
178}
179
180static 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
237static 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
259static 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
274static 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
282static 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
296Evas_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
302Ewk_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
312Eina_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
329Evas_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
338Eina_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
348const 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
354const 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
360const 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
379Eina_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
395static 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
426Eina_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
435Eina_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
446const 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
467Eina_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
474Eina_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
487const 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
497Eina_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
506unsigned 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
516Eina_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
525Eina_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
533Eina_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 */
543static 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 */
551static bool _ewk_frame_rect_is_negative_value(const WebCore::IntRect& rect)
552{
553    return (rect.x() < 0 || rect.y() < 0);
554}
555
556Eina_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
578Eina_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
586Eina_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
594Eina_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
602Eina_Bool ewk_frame_back(Evas_Object* ewkFrame)
603{
604    return ewk_frame_navigate(ewkFrame, -1);
605}
606
607Eina_Bool ewk_frame_forward(Evas_Object* ewkFrame)
608{
609    return ewk_frame_navigate(ewkFrame, 1);
610}
611
612Eina_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
623Eina_Bool ewk_frame_back_possible(Evas_Object* ewkFrame)
624{
625    return ewk_frame_navigate_possible(ewkFrame, -1);
626}
627
628Eina_Bool ewk_frame_forward_possible(Evas_Object* ewkFrame)
629{
630    return ewk_frame_navigate_possible(ewkFrame, 1);
631}
632
633Eina_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
641float 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
648Eina_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
656float 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
663Eina_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
671void 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
684Ewk_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
753Eina_Bool
754ewk_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
763Eina_Bool
764ewk_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
773Eina_Bool
774ewk_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
791Eina_Bool
792ewk_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
809Eina_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
834Eina_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
842void 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
850Eina_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
859Eina_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
866Eina_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->focusedElement();
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
887Eina_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
902Eina_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
920Eina_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
938Eina_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
957Eina_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
979static 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
1043Eina_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
1059Eina_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
1072Ewk_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 */
1099Evas_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 */
1111bool 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 */
1133bool 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 */
1188void 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 */
1202void 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 */
1217void 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 */
1230void 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 */
1244void 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 */
1261void 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 */
1275void 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 */
1289void 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 */
1302void 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 */
1316void 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 */
1327void 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 */
1338void 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 */
1359void 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 */
1373void 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 */
1386void 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 */
1399void 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 */
1412void 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 */
1429void 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 */
1461void 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 */
1472void 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 */
1483void 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 */
1511void 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 */
1530void 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 */
1541void 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 */
1556void 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
1587ssize_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
1632Eina_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
1668out_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
1676const 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
1692Eina_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
1698Eina_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
1704Ewk_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 */
1735void 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 */
1747bool 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 */
1769void 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 */
1784WTF::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 */
1824void 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 */
1839void 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 */
1858void 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 */
1881void 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 */
1901void 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
1906namespace EWKPrivate {
1907
1908WebCore::Frame* coreFrame(const Evas_Object* ewkFrame)
1909{
1910    EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, 0);
1911    return smartData->frame;
1912}
1913
1914Evas_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
1927