• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "DocumentMarkerController.h"
28 #include "EWebKit.h"
29 #include "EventHandler.h"
30 #include "FocusController.h"
31 #include "FrameLoaderClientEfl.h"
32 #include "FrameTree.h"
33 #include "FrameView.h"
34 #include "HTMLPlugInElement.h"
35 #include "HistoryItem.h"
36 #include "HitTestResult.h"
37 #include "IntSize.h"
38 #include "KURL.h"
39 #include "PlatformKeyboardEvent.h"
40 #include "PlatformMouseEvent.h"
41 #include "PlatformTouchEvent.h"
42 #include "PlatformWheelEvent.h"
43 #include "ProgressTracker.h"
44 #include "RefPtr.h"
45 #include "RenderTheme.h"
46 #include "ResourceRequest.h"
47 #include "ScriptValue.h"
48 #include "SharedBuffer.h"
49 #include "SubstituteData.h"
50 #include "WindowsKeyboardCodes.h"
51 #include "ewk_private.h"
52 
53 #include <Eina.h>
54 #include <Evas.h>
55 #include <algorithm>
56 #include <eina_safety_checks.h>
57 #include <wtf/text/CString.h>
58 
59 static const char EWK_FRAME_TYPE_STR[] = "EWK_Frame";
60 
61 struct Ewk_Frame_Smart_Data {
62     Evas_Object_Smart_Clipped_Data base;
63     Evas_Object* self;
64     Evas_Object* view;
65 #ifdef EWK_FRAME_DEBUG
66     Evas_Object* region;
67 #endif
68     WebCore::Frame* frame;
69     const char* theme;
70     const char* title;
71     const char* uri;
72     const char* name;
73     struct {
74         Evas_Coord w, h;
75     } contents_size;
76     Eina_Bool textZoom:1;
77     Eina_Bool editable:1;
78 };
79 
80 struct Eina_Iterator_Ewk_Frame {
81     Eina_Iterator base;
82     Evas_Object* obj;
83     WebCore::Frame* last;
84 };
85 
86 #ifndef EWK_TYPE_CHECK
87 #define EWK_FRAME_TYPE_CHECK(o, ...) do { } while (0)
88 #else
89 #define EWK_FRAME_TYPE_CHECK(o, ...)                                    \
90     do {                                                                \
91         const char* _tmp_otype = evas_object_type_get(o);               \
92         if (EINA_UNLIKELY(_tmp_otype != EWK_FRAME_TYPE_STR)) {          \
93             EINA_LOG_CRIT                                               \
94                 ("%p (%s) is not of an ewk_frame!", o,                  \
95                  _tmp_otype ? _tmp_otype : "(null)");                   \
96             return __VA_ARGS__;                                         \
97         }                                                               \
98     } while (0)
99 #endif
100 
101 #define EWK_FRAME_SD_GET(o, ptr)                                \
102     Ewk_Frame_Smart_Data* ptr = (Ewk_Frame_Smart_Data*)evas_object_smart_data_get(o)
103 
104 #define EWK_FRAME_SD_GET_OR_RETURN(o, ptr, ...)         \
105     EWK_FRAME_TYPE_CHECK(o, __VA_ARGS__);               \
106     EWK_FRAME_SD_GET(o, ptr);                           \
107     if (!ptr) {                                         \
108         CRITICAL("no smart data for object %p (%s)",    \
109                  o, evas_object_type_get(o));           \
110         return __VA_ARGS__;                             \
111     }
112 
113 static Evas_Smart_Class _parent_sc = EVAS_SMART_CLASS_INIT_NULL;
114 
115 #ifdef EWK_FRAME_DEBUG
_ewk_frame_debug(Evas_Object * o)116 static inline void _ewk_frame_debug(Evas_Object* o)
117 {
118     Evas_Object* clip, *parent;
119     Evas_Coord x, y, w, h, cx, cy, cw, ch;
120     int r, g, b, a, cr, cg, cb, ca;
121 
122     evas_object_color_get(o, &r, &g, &b, &a);
123     evas_object_geometry_get(o, &x, &y, &w, &h);
124 
125     clip = evas_object_clip_get(o);
126     evas_object_color_get(clip, &cr, &cg, &cb, &ca);
127     evas_object_geometry_get(clip, &cx, &cy, &cw, &ch);
128 
129     fprintf(stderr, "%p: type=%s name=%s, visible=%d, color=%02x%02x%02x%02x, %d,%d+%dx%d, clipper=%p (%d, %02x%02x%02x%02x, %d,%d+%dx%d)\n",
130             o, evas_object_type_get(o), evas_object_name_get(o), evas_object_visible_get(o),
131             r, g, b, a, x, y, w, h,
132             clip, evas_object_visible_get(clip), cr, cg, cb, ca, cx, cy, cw, ch);
133     parent = evas_object_smart_parent_get(o);
134     if (!parent)
135         fprintf(stderr, "\n");
136     else
137         _ewk_frame_debug(parent);
138 }
139 #endif
140 
_ewk_frame_loader_efl_get(WebCore::Frame * frame)141 static WebCore::FrameLoaderClientEfl* _ewk_frame_loader_efl_get(WebCore::Frame* frame)
142 {
143     return static_cast<WebCore::FrameLoaderClientEfl*>(frame->loader()->client());
144 }
145 
kit(WebCore::Frame * frame)146 static inline Evas_Object* kit(WebCore::Frame* frame)
147 {
148     if (!frame)
149         return 0;
150     WebCore::FrameLoaderClientEfl* fl = _ewk_frame_loader_efl_get(frame);
151     if (!fl)
152         return 0;
153     return fl->webFrame();
154 }
155 
_ewk_frame_children_iterator_next(Eina_Iterator_Ewk_Frame * it,Evas_Object ** data)156 static Eina_Bool _ewk_frame_children_iterator_next(Eina_Iterator_Ewk_Frame* it, Evas_Object** data)
157 {
158     EWK_FRAME_SD_GET_OR_RETURN(it->obj, sd, EINA_FALSE);
159     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
160 
161     WebCore::FrameTree* tree = sd->frame->tree(); // check if it's still valid
162     EINA_SAFETY_ON_NULL_RETURN_VAL(tree, EINA_FALSE);
163 
164     WebCore::Frame* frame;
165     if (it->last)
166         frame = it->last->tree()->nextSibling();
167     else
168         frame = tree->firstChild();
169 
170     if (!frame)
171         return EINA_FALSE;
172 
173     *data = kit(frame);
174     return EINA_TRUE;
175 }
176 
_ewk_frame_children_iterator_get_container(Eina_Iterator_Ewk_Frame * it)177 static Evas_Object* _ewk_frame_children_iterator_get_container(Eina_Iterator_Ewk_Frame* it)
178 {
179     return it->obj;
180 }
181 
_ewk_frame_smart_add(Evas_Object * o)182 static void _ewk_frame_smart_add(Evas_Object* o)
183 {
184     EWK_FRAME_SD_GET(o, sd);
185 
186     if (!sd) {
187         sd = (Ewk_Frame_Smart_Data*)calloc(1, sizeof(Ewk_Frame_Smart_Data));
188         if (!sd)
189             CRITICAL("could not allocate Ewk_Frame_Smart_Data");
190         else
191             evas_object_smart_data_set(o, sd);
192     }
193 
194     sd->self = o;
195 
196     _parent_sc.add(o);
197     evas_object_static_clip_set(sd->base.clipper, EINA_FALSE);
198     evas_object_move(sd->base.clipper, 0, 0);
199     evas_object_resize(sd->base.clipper, 0, 0);
200 
201 #ifdef EWK_FRAME_DEBUG
202     sd->region = evas_object_rectangle_add(sd->base.evas);
203     static int i = 0;
204     switch (i) {
205     case 0:
206         evas_object_color_set(sd->region, 128, 0, 0, 128);
207         break;
208     case 1:
209         evas_object_color_set(sd->region, 0, 128, 0, 128);
210         break;
211     case 2:
212         evas_object_color_set(sd->region, 0, 0, 128, 128);
213         break;
214     case 3:
215         evas_object_color_set(sd->region, 128, 0, 0, 128);
216         break;
217     case 4:
218         evas_object_color_set(sd->region, 128, 128, 0, 128);
219         break;
220     case 5:
221         evas_object_color_set(sd->region, 128, 0, 128, 128);
222         break;
223     case 6:
224         evas_object_color_set(sd->region, 0, 128, 128, 128);
225         break;
226     default:
227         break;
228     }
229     i++;
230     if (i > 6)
231         i = 0;
232 
233     evas_object_smart_member_add(sd->region, o);
234     evas_object_hide(sd->region);
235 #endif
236 }
237 
_ewk_frame_smart_del(Evas_Object * o)238 static void _ewk_frame_smart_del(Evas_Object* o)
239 {
240     WRN("o=%p", o); // XXX REMOVE ME LATER
241     EWK_FRAME_SD_GET(o, sd);
242 
243     if (sd) {
244         if (sd->frame) {
245             WebCore::FrameLoaderClientEfl* flc = _ewk_frame_loader_efl_get(sd->frame);
246             flc->setWebFrame(0);
247             sd->frame->loader()->cancelAndClear();
248             sd->frame = 0;
249         }
250 
251         eina_stringshare_del(sd->title);
252         eina_stringshare_del(sd->uri);
253         eina_stringshare_del(sd->name);
254     }
255 
256     _parent_sc.del(o);
257 }
258 
_ewk_frame_smart_resize(Evas_Object * o,Evas_Coord w,Evas_Coord h)259 static void _ewk_frame_smart_resize(Evas_Object* o, Evas_Coord w, Evas_Coord h)
260 {
261     EWK_FRAME_SD_GET(o, sd);
262     evas_object_resize(sd->base.clipper, w, h);
263 
264 #ifdef EWK_FRAME_DEBUG
265     evas_object_resize(sd->region, w, h);
266     Evas_Coord x, y;
267     evas_object_geometry_get(sd->region, &x, &y, &w, &h);
268     INF("region=%p, visible=%d, geo=%d,%d + %dx%d",
269         sd->region, evas_object_visible_get(sd->region), x, y, w, h);
270     _ewk_frame_debug(o);
271 #endif
272 }
273 
_ewk_frame_smart_set(Evas_Smart_Class * api)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 
_ewk_frame_smart_class_new(void)282 static inline Evas_Smart* _ewk_frame_smart_class_new(void)
283 {
284     static Evas_Smart_Class sc = 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(&sc);
290         smart = evas_smart_class_new(&sc);
291     }
292 
293     return smart;
294 }
295 
296 /**
297  * @internal
298  *
299  * Creates a new EFL WebKit Frame object.
300  *
301  * Frames are low level entries contained in a page that is contained
302  * by a view. Usually one operates on the view and not directly on the
303  * frame.
304  *
305  * @param e canvas where to create the frame object.
306  *
307  * @return frame object or @c NULL if errors.
308  */
ewk_frame_add(Evas * e)309 Evas_Object* ewk_frame_add(Evas* e)
310 {
311     return evas_object_smart_add(e, _ewk_frame_smart_class_new());
312 }
313 
314 /**
315  * Retrieves the ewk_view object that owns this frame.
316  *
317  * @param o frame object to get view from.
318  *
319  * @return view object or @c NULL if errors.
320  */
ewk_frame_view_get(const Evas_Object * o)321 Evas_Object* ewk_frame_view_get(const Evas_Object* o)
322 {
323     EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
324     return sd->view;
325 }
326 
327 /**
328  * Set the theme path to be used by this frame.
329  *
330  * Frames inherit theme from their parent, this will have all frames
331  * with unset theme to use this one.
332  *
333  * @param o frame object to change theme.
334  * @param path theme path, may be @c NULL to reset to default or inherit parent.
335  */
ewk_frame_theme_set(Evas_Object * o,const char * path)336 void ewk_frame_theme_set(Evas_Object* o, const char* path)
337 {
338     EWK_FRAME_SD_GET_OR_RETURN(o, sd);
339     if (!eina_stringshare_replace(&sd->theme, path))
340         return;
341     if (sd->frame && sd->frame->view()) {
342         sd->frame->view()->setEdjeTheme(WTF::String(path));
343         sd->frame->page()->theme()->themeChanged();
344     }
345 }
346 
347 /**
348  * Gets the immediate theme set on this frame.
349  *
350  * This returns the value set by ewk_frame_theme_set(). Note that if
351  * it is @c NULL, the frame will inherit parent's theme.
352  *
353  * @param o frame object to get theme path.
354  *
355  * @return theme path, may be @c NULL if not set.
356  */
ewk_frame_theme_get(Evas_Object * o)357 const char* ewk_frame_theme_get(Evas_Object* o)
358 {
359     EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
360     return sd->theme;
361 }
362 
363 /**
364  * Returns a new iterator over all direct children frames.
365  *
366  * Keep frame object intact while iteration happens otherwise frame
367  * may be destroyed while iterated.
368  *
369  * Iteration results are Evas_Object*, so give eina_iterator_next() a
370  * pointer to it.
371  *
372  * @return a newly allocated iterator, free using
373  *         eina_iterator_free(). If not possible to create the
374  *         iterator, @c NULL is returned.
375  */
ewk_frame_children_iterator_new(Evas_Object * o)376 Eina_Iterator* ewk_frame_children_iterator_new(Evas_Object* o)
377 {
378     EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
379     Eina_Iterator_Ewk_Frame* it = (Eina_Iterator_Ewk_Frame*)
380         calloc(1, sizeof(Eina_Iterator_Ewk_Frame));
381     if (!it)
382         return 0;
383 
384     EINA_MAGIC_SET(&it->base, EINA_MAGIC_ITERATOR);
385     it->base.next = FUNC_ITERATOR_NEXT(_ewk_frame_children_iterator_next);
386     it->base.get_container = FUNC_ITERATOR_GET_CONTAINER(_ewk_frame_children_iterator_get_container);
387     it->base.free = FUNC_ITERATOR_FREE(free);
388     it->obj = o;
389     return &it->base;
390 }
391 
392 /**
393  * Finds a child frame by its name, recursively.
394  *
395  * For pre-defined names, returns @a o if @a name is "_self" or
396  * "_current", returns @a o's parent frame if @a name is "_parent",
397  * and returns the main frame if @a name is "_top". Also returns @a o
398  * if it is the main frame and @a name is either "_parent" or
399  * "_top". For other names, this function returns the first frame that
400  * matches @a name. This function searches @a o and its descendents
401  * first, then @a o's parent and its children moving up the hierarchy
402  * until a match is found. If no match is found in @a o's hierarchy,
403  * this function will search for a matching frame in other main frame
404  * hierarchies.
405  *
406  * @return object if found, @c NULL if nothing with that name.
407  */
ewk_frame_child_find(Evas_Object * o,const char * name)408 Evas_Object* ewk_frame_child_find(Evas_Object* o, const char* name)
409 {
410     EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
411     EINA_SAFETY_ON_NULL_RETURN_VAL(name, 0);
412     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, 0);
413     WTF::String s = WTF::String::fromUTF8(name);
414     return kit(sd->frame->tree()->find(WTF::AtomicString(s)));
415 }
416 
417 /**
418  * Ask main frame to load the given URI.
419  *
420  * @param o frame object to load uri.
421  * @param uri uniform resource identifier to load.
422  */
ewk_frame_uri_set(Evas_Object * o,const char * uri)423 Eina_Bool ewk_frame_uri_set(Evas_Object* o, const char* uri)
424 {
425     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
426     WebCore::KURL kurl(WebCore::KURL(), WTF::String::fromUTF8(uri));
427     WebCore::ResourceRequest req(kurl);
428     WebCore::FrameLoader* loader = sd->frame->loader();
429     loader->load(req, false);
430     return EINA_TRUE;
431 }
432 
433 /**
434  * Gets the uri of this frame.
435  *
436  * @param o frame object to get uri.
437  *
438  * @return frame uri or @c NULL. It's a internal string and should
439  *         not be modified. The string is guaranteed to be stringshared.
440  */
ewk_frame_uri_get(const Evas_Object * o)441 const char* ewk_frame_uri_get(const Evas_Object* o)
442 {
443     EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
444     return sd->uri;
445 }
446 
447 /**
448  * Gets the title of this frame.
449  *
450  * @param o frame object to get title.
451  *
452  * @return frame title or @c NULL. It's a internal string and should
453  *         not be modified. The string is guaranteed to be stringshared.
454  */
ewk_frame_title_get(const Evas_Object * o)455 const char* ewk_frame_title_get(const Evas_Object* o)
456 {
457     EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
458     return sd->title;
459 }
460 
461 /**
462  * Gets the name of this frame.
463  *
464  * @param o frame object to get name.
465  *
466  * @return frame name or @c NULL. It's a internal string and should
467  *         not be modified. The string is guaranteed to be stringshared.
468  */
ewk_frame_name_get(const Evas_Object * o)469 const char* ewk_frame_name_get(const Evas_Object* o)
470 {
471     EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
472 
473     if (sd->name)
474         return sd->name;
475 
476     if (!sd->frame) {
477         ERR("could not get name of uninitialized frame.");
478         return 0;
479     }
480 
481     WTF::String s = sd->frame->tree()->uniqueName();
482     WTF::CString cs = s.utf8();
483     sd->name = eina_stringshare_add_length(cs.data(), cs.length());
484     return sd->name;
485 }
486 
487 /**
488  * Get last known contents size.
489  *
490  * @param o frame object to get contents size.
491  * @param w where to store contents size width. May be @c NULL.
492  * @param h where to store contents size height. May be @c NULL.
493  *
494  * @return @c EINA_TRUE on success or @c EINA_FALSE on failure and
495  *         @a w and @a h will be zeroed.
496  */
ewk_frame_contents_size_get(const Evas_Object * o,Evas_Coord * w,Evas_Coord * h)497 Eina_Bool ewk_frame_contents_size_get(const Evas_Object* o, Evas_Coord* w, Evas_Coord* h)
498 {
499     if (w)
500         *w = 0;
501     if (h)
502         *h = 0;
503     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
504     if (w)
505         *w = sd->contents_size.w;
506     if (h)
507         *h = sd->contents_size.h;
508     return EINA_TRUE;
509 }
510 
_ewk_frame_contents_set_internal(Ewk_Frame_Smart_Data * sd,const char * contents,size_t contents_size,const char * mime_type,const char * encoding,const char * base_uri,const char * unreachable_uri)511 static Eina_Bool _ewk_frame_contents_set_internal(Ewk_Frame_Smart_Data *sd, const char* contents, size_t contents_size, const char* mime_type, const char* encoding, const char* base_uri, const char* unreachable_uri)
512 {
513     size_t len = strlen(contents);
514     if (contents_size < 1 || contents_size > len)
515         contents_size = len;
516     if (!mime_type)
517         mime_type = "text/html";
518     if (!encoding)
519         encoding = "UTF-8";
520     if (!base_uri)
521         base_uri = "about:blank";
522 
523     WebCore::KURL baseKURL(WebCore::KURL(), WTF::String::fromUTF8(base_uri));
524     WebCore::KURL unreachableKURL;
525     if (unreachable_uri)
526         unreachableKURL = WebCore::KURL(WebCore::KURL(), WTF::String::fromUTF8(unreachable_uri));
527     else
528         unreachableKURL = WebCore::KURL();
529 
530     WTF::RefPtr<WebCore::SharedBuffer> buffer = WebCore::SharedBuffer::create(contents, contents_size);
531     WebCore::SubstituteData substituteData
532         (buffer.release(),
533          WTF::String::fromUTF8(mime_type),
534          WTF::String::fromUTF8(encoding),
535          baseKURL, unreachableKURL);
536     WebCore::ResourceRequest request(baseKURL);
537 
538     sd->frame->loader()->load(request, substituteData, false);
539     return EINA_TRUE;
540 }
541 
542 /**
543  * Requests loading the given contents in this frame.
544  *
545  * @param o frame object to load document.
546  * @param contents what to load into frame. Must not be @c NULL.
547  * @param contents_size byte size of data in @a contents.
548  *        If zero, strlen() is used.
549  * @param mime_type type of @a contents data. If @c NULL "text/html" is assumed.
550  * @param encoding used for @a contents data. If @c NULL "UTF-8" is assumed.
551  * @param base_uri base uri to use for relative resources. May be @c NULL.
552  *        If provided must be an absolute uri.
553  *
554  * @return @c EINA_TRUE on successful request, @c EINA_FALSE on errors.
555  */
ewk_frame_contents_set(Evas_Object * o,const char * contents,size_t contents_size,const char * mime_type,const char * encoding,const char * base_uri)556 Eina_Bool ewk_frame_contents_set(Evas_Object* o, const char* contents, size_t contents_size, const char* mime_type, const char* encoding, const char* base_uri)
557 {
558     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
559     EINA_SAFETY_ON_FALSE_RETURN_VAL(sd->frame, EINA_FALSE);
560     EINA_SAFETY_ON_NULL_RETURN_VAL(contents, EINA_FALSE);
561     return _ewk_frame_contents_set_internal
562         (sd, contents, contents_size, mime_type, encoding, base_uri, 0);
563 }
564 
565 /**
566  * Requests loading alternative contents for unreachable URI in this frame.
567  *
568  * This is similar to ewk_frame_contents_set(), but is used when some
569  * URI failed to load, using the provided content instead. The main
570  * difference is that back-forward navigation list is not changed.
571  *
572  * @param o frame object to load document.
573  * @param contents what to load into frame. Must not be @c NULL.
574  * @param contents_size byte size of data in @a contents.
575  *        If zero, strlen() is used.
576  * @param mime_type type of @a contents data. If @c NULL "text/html" is assumed.
577  * @param encoding used for @a contents data. If @c NULL "UTF-8" is assumed.
578  * @param base_uri base uri to use for relative resources. May be @c NULL.
579  *        If provided must be an absolute uri.
580  * @param unreachable_uri the URI that failed to load and is getting the
581  *        alternative representation.
582  *
583  * @return @c EINA_TRUE on successful request, @c EINA_FALSE on errors.
584  */
ewk_frame_contents_alternate_set(Evas_Object * o,const char * contents,size_t contents_size,const char * mime_type,const char * encoding,const char * base_uri,const char * unreachable_uri)585 Eina_Bool ewk_frame_contents_alternate_set(Evas_Object* o, const char* contents, size_t contents_size, const char* mime_type, const char* encoding, const char* base_uri, const char* unreachable_uri)
586 {
587     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
588     EINA_SAFETY_ON_FALSE_RETURN_VAL(sd->frame, EINA_FALSE);
589     EINA_SAFETY_ON_NULL_RETURN_VAL(contents, EINA_FALSE);
590     EINA_SAFETY_ON_NULL_RETURN_VAL(unreachable_uri, EINA_FALSE);
591     return _ewk_frame_contents_set_internal
592         (sd, contents, contents_size, mime_type, encoding, base_uri,
593          unreachable_uri);
594 }
595 
596 /**
597  * Requests execution of given script.
598  *
599  * @param o frame object to execute script.
600  * @param script java script to execute.
601  *
602  * @return @c EINA_TRUE if request was done, @c EINA_FALSE on errors.
603  */
ewk_frame_script_execute(Evas_Object * o,const char * script)604 Eina_Bool ewk_frame_script_execute(Evas_Object* o, const char* script)
605 {
606     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
607     EINA_SAFETY_ON_FALSE_RETURN_VAL(sd->frame, EINA_FALSE);
608     EINA_SAFETY_ON_NULL_RETURN_VAL(script, EINA_FALSE);
609     sd->frame->script()->executeScript(WTF::String::fromUTF8(script), true);
610     return EINA_TRUE;
611 }
612 
613 /**
614  * Gets if frame is editable.
615  *
616  * @param o frame object to get editable state.
617  *
618  * @return @c EINA_TRUE if editable, @c EINA_FALSE otherwise.
619  */
ewk_frame_editable_get(const Evas_Object * o)620 Eina_Bool ewk_frame_editable_get(const Evas_Object* o)
621 {
622     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
623     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
624     return sd->editable;
625 }
626 
627 /**
628  * Sets if frame is editable.
629  *
630  * @param o frame object to set editable state.
631  * @param editable new state.
632  *
633  * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
634  */
ewk_frame_editable_set(Evas_Object * o,Eina_Bool editable)635 Eina_Bool ewk_frame_editable_set(Evas_Object* o, Eina_Bool editable)
636 {
637     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
638     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
639     editable = !!editable;
640     if (sd->editable == editable)
641         return EINA_TRUE;
642     if (editable)
643         sd->frame->editor()->applyEditingStyleToBodyElement();
644     return EINA_TRUE;
645 }
646 
647 /**
648  * Get the copy of the selection text.
649  *
650  * @param o frame object to get selection text.
651  *
652  * @return newly allocated string or @c NULL if nothing is selected or failure.
653  */
ewk_frame_selection_get(const Evas_Object * o)654 char* ewk_frame_selection_get(const Evas_Object* o)
655 {
656     EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
657     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, 0);
658     WTF::CString s = sd->frame->editor()->selectedText().utf8();
659     if (s.isNull())
660         return 0;
661     return strdup(s.data());
662 }
663 
_ewk_frame_editor_command(Ewk_Frame_Smart_Data * sd,const char * command)664 static inline Eina_Bool _ewk_frame_editor_command(Ewk_Frame_Smart_Data* sd, const char* command)
665 {
666     return sd->frame->editor()->command(WTF::String::fromUTF8(command)).execute();
667 }
668 
669 /**
670  * Unselects whatever was selected.
671  *
672  * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
673  */
ewk_frame_select_none(Evas_Object * o)674 Eina_Bool ewk_frame_select_none(Evas_Object* o)
675 {
676     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
677     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
678     return _ewk_frame_editor_command(sd, "Unselect");
679 }
680 
681 /**
682  * Selects everything.
683  *
684  * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
685  */
ewk_frame_select_all(Evas_Object * o)686 Eina_Bool ewk_frame_select_all(Evas_Object* o)
687 {
688     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
689     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
690     return _ewk_frame_editor_command(sd, "SelectAll");
691 }
692 
693 /**
694  * Selects the current paragrah.
695  *
696  * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
697  */
ewk_frame_select_paragraph(Evas_Object * o)698 Eina_Bool ewk_frame_select_paragraph(Evas_Object* o)
699 {
700     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
701     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
702     return _ewk_frame_editor_command(sd, "SelectParagraph");
703 }
704 
705 /**
706  * Selects the current sentence.
707  *
708  * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
709  */
ewk_frame_select_sentence(Evas_Object * o)710 Eina_Bool ewk_frame_select_sentence(Evas_Object* o)
711 {
712     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
713     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
714     return _ewk_frame_editor_command(sd, "SelectSentence");
715 }
716 
717 /**
718  * Selects the current line.
719  *
720  * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
721  */
ewk_frame_select_line(Evas_Object * o)722 Eina_Bool ewk_frame_select_line(Evas_Object* o)
723 {
724     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
725     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
726     return _ewk_frame_editor_command(sd, "SelectLine");
727 }
728 
729 /**
730  * Selects the current word.
731  *
732  * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
733  */
ewk_frame_select_word(Evas_Object * o)734 Eina_Bool ewk_frame_select_word(Evas_Object* o)
735 {
736     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
737     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
738     return _ewk_frame_editor_command(sd, "SelectWord");
739 }
740 
741 /**
742  * Search the given text string in document.
743  *
744  * @param o frame object where to search text.
745  * @param string reference string to search.
746  * @param case_sensitive if search should be case sensitive or not.
747  * @param forward if search is from cursor and on or backwards.
748  * @param wrap if search should wrap at end.
749  *
750  * @return @c EINA_TRUE if found, @c EINA_FALSE if not or failure.
751  */
ewk_frame_text_search(const Evas_Object * o,const char * string,Eina_Bool case_sensitive,Eina_Bool forward,Eina_Bool wrap)752 Eina_Bool ewk_frame_text_search(const Evas_Object* o, const char* string, Eina_Bool case_sensitive, Eina_Bool forward, Eina_Bool wrap)
753 {
754     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
755     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
756     EINA_SAFETY_ON_NULL_RETURN_VAL(string, EINA_FALSE);
757 
758     return sd->frame->editor()->findString(WTF::String::fromUTF8(string), forward, case_sensitive, wrap, true);
759 }
760 
761 /**
762  * Mark matches the given text string in document.
763  *
764  * @param o frame object where to search text.
765  * @param string reference string to match.
766  * @param case_sensitive if match should be case sensitive or not.
767  * @param highlight if matches should be highlighted.
768  * @param limit maximum amount of matches, or zero to unlimited.
769  *
770  * @return number of matches.
771  */
ewk_frame_text_matches_mark(Evas_Object * o,const char * string,Eina_Bool case_sensitive,Eina_Bool highlight,unsigned int limit)772 unsigned int ewk_frame_text_matches_mark(Evas_Object* o, const char* string, Eina_Bool case_sensitive, Eina_Bool highlight, unsigned int limit)
773 {
774     EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
775     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
776     EINA_SAFETY_ON_NULL_RETURN_VAL(string, 0);
777 
778     sd->frame->editor()->setMarkedTextMatchesAreHighlighted(highlight);
779     return sd->frame->editor()->countMatchesForText(WTF::String::fromUTF8(string), case_sensitive, limit, true);
780 }
781 
782 /**
783  * Reverses the effect of ewk_frame_text_matches_mark()
784  *
785  * @param o frame object where to search text.
786  *
787  * @return @c EINA_TRUE on success, @c EINA_FALSE for failure.
788  */
ewk_frame_text_matches_unmark_all(Evas_Object * o)789 Eina_Bool ewk_frame_text_matches_unmark_all(Evas_Object* o)
790 {
791     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
792     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
793 
794     sd->frame->document()->markers()->removeMarkers(WebCore::DocumentMarker::TextMatch);
795     return EINA_TRUE;
796 }
797 
798 /**
799  * Set if should highlight matches marked with ewk_frame_text_matches_mark().
800  *
801  * @param o frame object where to set if matches are highlighted or not.
802  * @param highlight if @c EINA_TRUE, matches will be highlighted.
803  *
804  * @return @c EINA_TRUE on success, @c EINA_FALSE for failure.
805  */
ewk_frame_text_matches_highlight_set(Evas_Object * o,Eina_Bool highlight)806 Eina_Bool ewk_frame_text_matches_highlight_set(Evas_Object* o, Eina_Bool highlight)
807 {
808     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
809     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
810     sd->frame->editor()->setMarkedTextMatchesAreHighlighted(highlight);
811     return EINA_TRUE;
812 }
813 
814 /**
815  * Get if should highlight matches marked with ewk_frame_text_matches_mark().
816  *
817  * @param o frame object to query if matches are highlighted or not.
818  *
819  * @return @c EINA_TRUE if they are highlighted, @c EINA_FALSE otherwise.
820  */
ewk_frame_text_matches_highlight_get(const Evas_Object * o)821 Eina_Bool ewk_frame_text_matches_highlight_get(const Evas_Object* o)
822 {
823     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
824     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
825     return sd->frame->editor()->markedTextMatchesAreHighlighted();
826 }
827 
828 /**
829  * Comparison function used by ewk_frame_text_matches_nth_pos_get
830  */
_ewk_frame_rect_cmp_less_than(const WebCore::IntRect & i,const WebCore::IntRect & j)831 static bool _ewk_frame_rect_cmp_less_than(const WebCore::IntRect& i, const WebCore::IntRect& j)
832 {
833     return (i.y() < j.y() || (i.y() == j.y() && i.x() < j.x()));
834 }
835 
836 /**
837  * Predicate used by ewk_frame_text_matches_nth_pos_get
838  */
_ewk_frame_rect_is_negative_value(const WebCore::IntRect & i)839 static bool _ewk_frame_rect_is_negative_value(const WebCore::IntRect& i)
840 {
841     return (i.x() < 0 || i.y() < 0);
842 }
843 
844 /**
845  * Get x, y position of n-th text match in frame
846  *
847  * @param o frame object where matches are highlighted.
848  * @param n index of element
849  * @param x where to return x position. May be @c NULL.
850  * @param y where to return y position. May be @c NULL.
851  *
852  * @return @c EINA_TRUE on success, @c EINA_FALSE for failure - when no matches found or
853  *         n bigger than search results.
854  */
ewk_frame_text_matches_nth_pos_get(Evas_Object * o,size_t n,int * x,int * y)855 Eina_Bool ewk_frame_text_matches_nth_pos_get(Evas_Object* o, size_t n, int* x, int* y)
856 {
857     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
858     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
859 
860     Vector<WebCore::IntRect> intRects = sd->frame->document()->markers()->renderedRectsForMarkers(WebCore::DocumentMarker::TextMatch);
861 
862     /* remove useless values */
863     std::remove_if(intRects.begin(), intRects.end(), _ewk_frame_rect_is_negative_value);
864 
865     if (intRects.isEmpty() || n > intRects.size())
866       return EINA_FALSE;
867 
868     std::sort(intRects.begin(), intRects.end(), _ewk_frame_rect_cmp_less_than);
869 
870     if (x)
871       *x = intRects[n - 1].x();
872     if (y)
873       *y = intRects[n - 1].y();
874     return EINA_TRUE;
875 }
876 
877 /**
878  * Ask frame to stop loading.
879  *
880  * @param o frame object to stop loading.
881  *
882  * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
883  */
ewk_frame_stop(Evas_Object * o)884 Eina_Bool ewk_frame_stop(Evas_Object* o)
885 {
886     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
887     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
888     sd->frame->loader()->stopAllLoaders();
889     return EINA_TRUE;
890 }
891 
892 /**
893  * Ask frame to reload current document.
894  *
895  * @param o frame object to reload.
896  *
897  * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
898  *
899  * @see ewk_frame_reload_full()
900  */
ewk_frame_reload(Evas_Object * o)901 Eina_Bool ewk_frame_reload(Evas_Object* o)
902 {
903     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
904     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
905     sd->frame->loader()->reload();
906     return EINA_TRUE;
907 }
908 
909 /**
910  * Ask frame to fully reload current document, using no previous caches.
911  *
912  * @param o frame object to reload.
913  *
914  * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
915  */
ewk_frame_reload_full(Evas_Object * o)916 Eina_Bool ewk_frame_reload_full(Evas_Object* o)
917 {
918     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
919     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
920     sd->frame->loader()->reload(true);
921     return EINA_TRUE;
922 }
923 
924 /**
925  * Ask frame to navigate back in history.
926  *
927  * @param o frame object to navigate back.
928  *
929  * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
930  *
931  * @see ewk_frame_navigate()
932  */
ewk_frame_back(Evas_Object * o)933 Eina_Bool ewk_frame_back(Evas_Object* o)
934 {
935     return ewk_frame_navigate(o, -1);
936 }
937 
938 /**
939  * Ask frame to navigate forward in history.
940  *
941  * @param o frame object to navigate forward.
942  *
943  * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
944  *
945  * @see ewk_frame_navigate()
946  */
ewk_frame_forward(Evas_Object * o)947 Eina_Bool ewk_frame_forward(Evas_Object* o)
948 {
949     return ewk_frame_navigate(o, 1);
950 }
951 
952 /**
953  * Navigate back or forward in history.
954  *
955  * @param o frame object to navigate.
956  * @param steps if positive navigates that amount forwards, if negative
957  *        does backwards.
958  *
959  * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
960  */
ewk_frame_navigate(Evas_Object * o,int steps)961 Eina_Bool ewk_frame_navigate(Evas_Object* o, int steps)
962 {
963     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
964     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
965     WebCore::Page* page = sd->frame->page();
966     if (!page->canGoBackOrForward(steps))
967         return EINA_FALSE;
968     page->goBackOrForward(steps);
969     return EINA_TRUE;
970 }
971 
972 /**
973  * Check if it is possible to navigate backwards one item in history.
974  *
975  * @param o frame object to check if backward navigation is possible.
976  *
977  * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise.
978  *
979  * @see ewk_frame_navigate_possible()
980  */
ewk_frame_back_possible(Evas_Object * o)981 Eina_Bool ewk_frame_back_possible(Evas_Object* o)
982 {
983     return ewk_frame_navigate_possible(o, -1);
984 }
985 
986 /**
987  * Check if it is possible to navigate forwards one item in history.
988  *
989  * @param o frame object to check if forward navigation is possible.
990  *
991  * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise.
992  *
993  * @see ewk_frame_navigate_possible()
994  */
ewk_frame_forward_possible(Evas_Object * o)995 Eina_Bool ewk_frame_forward_possible(Evas_Object* o)
996 {
997     return ewk_frame_navigate_possible(o, 1);
998 }
999 
1000 /**
1001  * Check if it is possible to navigate given @a steps in history.
1002  *
1003  * @param o frame object to navigate.
1004  * @param steps if positive navigates that amount forwards, if negative
1005  *        does backwards.
1006  *
1007  * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise.
1008  */
ewk_frame_navigate_possible(Evas_Object * o,int steps)1009 Eina_Bool ewk_frame_navigate_possible(Evas_Object* o, int steps)
1010 {
1011     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1012     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1013     WebCore::Page* page = sd->frame->page();
1014     return page->canGoBackOrForward(steps);
1015 }
1016 
1017 /**
1018  * Get current zoom level used by this frame.
1019  *
1020  * @param o frame object to query zoom level.
1021  *
1022  * @return zoom level or -1.0 on failure.
1023  */
ewk_frame_zoom_get(const Evas_Object * o)1024 float ewk_frame_zoom_get(const Evas_Object* o)
1025 {
1026     EWK_FRAME_SD_GET_OR_RETURN(o, sd, -1.0);
1027     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, -1.0);
1028 
1029     if (sd->textZoom)
1030         return sd->frame->textZoomFactor();
1031     return sd->frame->pageZoomFactor();
1032 }
1033 
1034 /**
1035  * Set current zoom level used by this frame.
1036  *
1037  * @param o frame object to change zoom level.
1038  * @param zoom new level.
1039  *
1040  * @return @c EINA_TRUE on success or @c EINA_FALSE on failure.
1041  *
1042  * @see ewk_frame_zoom_text_only_set()
1043  */
ewk_frame_zoom_set(Evas_Object * o,float zoom)1044 Eina_Bool ewk_frame_zoom_set(Evas_Object* o, float zoom)
1045 {
1046     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1047     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1048     if (sd->textZoom)
1049         sd->frame->setTextZoomFactor(zoom);
1050     else
1051         sd->frame->setPageZoomFactor(zoom);
1052     return EINA_TRUE;
1053 }
1054 
1055 /**
1056  * Query if zoom level just applies to text and not other elements.
1057  *
1058  * @param o frame to query setting.
1059  *
1060  * @return @c EINA_TRUE if just text are scaled, @c EINA_FALSE otherwise.
1061  */
ewk_frame_zoom_text_only_get(const Evas_Object * o)1062 Eina_Bool ewk_frame_zoom_text_only_get(const Evas_Object* o)
1063 {
1064     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1065     return sd->textZoom;
1066 }
1067 
1068 /**
1069  * Set if zoom level just applies to text and not other elements.
1070  *
1071  * @param o frame to change setting.
1072  * @param setting @c EINA_TRUE if zoom should just be applied to text.
1073  *
1074  * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1075  */
ewk_frame_zoom_text_only_set(Evas_Object * o,Eina_Bool setting)1076 Eina_Bool ewk_frame_zoom_text_only_set(Evas_Object* o, Eina_Bool setting)
1077 {
1078     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1079     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1080     if (sd->textZoom == setting)
1081         return EINA_TRUE;
1082 
1083     float zoom_level = sd->textZoom ? sd->frame->textZoomFactor() : sd->frame->pageZoomFactor();
1084     sd->textZoom = setting;
1085     if (sd->textZoom)
1086         sd->frame->setPageAndTextZoomFactors(1, zoom_level);
1087     else
1088         sd->frame->setPageAndTextZoomFactors(zoom_level, 1);
1089     return EINA_TRUE;
1090 }
1091 
1092 /**
1093  * Free hit test created with ewk_frame_hit_test_new().
1094  *
1095  * @param hit_test instance. Must @b not be @c NULL.
1096  */
ewk_frame_hit_test_free(Ewk_Hit_Test * hit_test)1097 void ewk_frame_hit_test_free(Ewk_Hit_Test* hit_test)
1098 {
1099     EINA_SAFETY_ON_NULL_RETURN(hit_test);
1100     eina_stringshare_del(hit_test->title);
1101     eina_stringshare_del(hit_test->alternate_text);
1102     eina_stringshare_del(hit_test->link.text);
1103     eina_stringshare_del(hit_test->link.url);
1104     eina_stringshare_del(hit_test->link.title);
1105     free(hit_test);
1106 }
1107 
1108 /**
1109  * Creates a new hit test for given frame and point.
1110  *
1111  * @param o frame to do hit test on.
1112  * @param x horizontal position to query.
1113  * @param y vertical position to query.
1114  *
1115  * @return a newly allocated hit test on success, @c NULL otherwise.
1116  *         Free memory with ewk_frame_hit_test_free()
1117  */
ewk_frame_hit_test_new(const Evas_Object * o,int x,int y)1118 Ewk_Hit_Test* ewk_frame_hit_test_new(const Evas_Object* o, int x, int y)
1119 {
1120     EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
1121     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, 0);
1122 
1123     WebCore::FrameView* view = sd->frame->view();
1124     EINA_SAFETY_ON_NULL_RETURN_VAL(view, 0);
1125     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame->contentRenderer(), 0);
1126 
1127     WebCore::HitTestResult result = sd->frame->eventHandler()->hitTestResultAtPoint
1128         (view->windowToContents(WebCore::IntPoint(x, y)),
1129          /*allowShadowContent*/ false, /*ignoreClipping*/ true);
1130 
1131     if (result.scrollbar())
1132         return 0;
1133     if (!result.innerNode())
1134         return 0;
1135 
1136     Ewk_Hit_Test* hit_test = (Ewk_Hit_Test*)calloc(1, sizeof(Ewk_Hit_Test));
1137     if (!hit_test) {
1138         CRITICAL("Could not allocate memory for hit test.");
1139         return 0;
1140     }
1141 
1142     hit_test->x = result.point().x();
1143     hit_test->y = result.point().y();
1144 #if 0
1145     // FIXME
1146     hit_test->bounding_box.x = result.boundingBox().x();
1147     hit_test->bounding_box.y = result.boundingBox().y();
1148     hit_test->bounding_box.w = result.boundingBox().width();
1149     hit_test->bounding_box.h = result.boundingBox().height();
1150 #else
1151     hit_test->bounding_box.x = 0;
1152     hit_test->bounding_box.y = 0;
1153     hit_test->bounding_box.w = 0;
1154     hit_test->bounding_box.h = 0;
1155 #endif
1156 
1157     WebCore::TextDirection dir;
1158     hit_test->title = eina_stringshare_add(result.title(dir).utf8().data());
1159     hit_test->alternate_text = eina_stringshare_add(result.altDisplayString().utf8().data());
1160     if (result.innerNonSharedNode() && result.innerNonSharedNode()->document()
1161         && result.innerNonSharedNode()->document()->frame())
1162         hit_test->frame = kit(result.innerNonSharedNode()->document()->frame());
1163 
1164     hit_test->link.text = eina_stringshare_add(result.textContent().utf8().data());
1165     hit_test->link.url = eina_stringshare_add(result.absoluteLinkURL().prettyURL().utf8().data());
1166     hit_test->link.title = eina_stringshare_add(result.titleDisplayString().utf8().data());
1167     hit_test->link.target_frame = kit(result.targetFrame());
1168 
1169     hit_test->flags.editable = result.isContentEditable();
1170     hit_test->flags.selected = result.isSelected();
1171 
1172     return hit_test;
1173 }
1174 
1175 /**
1176  * Relative scroll of given frame.
1177  *
1178  * @param o frame object to scroll.
1179  * @param dx horizontal offset to scroll.
1180  * @param dy vertical offset to scroll.
1181  *
1182  * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise.
1183  */
1184 Eina_Bool
ewk_frame_scroll_add(Evas_Object * o,int dx,int dy)1185 ewk_frame_scroll_add(Evas_Object* o, int dx, int dy)
1186 {
1187     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1188     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1189     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame->view(), EINA_FALSE);
1190     sd->frame->view()->scrollBy(WebCore::IntSize(dx, dy));
1191     return EINA_TRUE;
1192 }
1193 
1194 /**
1195  * Set absolute scroll of given frame.
1196  *
1197  * Both values are from zero to the contents size minus the viewport
1198  * size. See ewk_frame_scroll_size_get().
1199  *
1200  * @param o frame object to scroll.
1201  * @param x horizontal position to scroll.
1202  * @param y vertical position to scroll.
1203  *
1204  * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise.
1205  */
1206 Eina_Bool
ewk_frame_scroll_set(Evas_Object * o,int x,int y)1207 ewk_frame_scroll_set(Evas_Object* o, int x, int y)
1208 {
1209     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1210     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1211     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame->view(), EINA_FALSE);
1212     sd->frame->view()->setScrollPosition(WebCore::IntPoint(x, y));
1213     return EINA_TRUE;
1214 }
1215 
1216 /**
1217  * Get the possible scroll size of given frame.
1218  *
1219  * Possible scroll size is contents size minus the viewport
1220  * size. It's the last allowed value for ewk_frame_scroll_set()
1221  *
1222  * @param o frame object to scroll.
1223  * @param w where to return horizontal size that is possible to
1224  *        scroll. May be @c NULL.
1225  * @param h where to return vertical size that is possible to scroll.
1226  *        May be @c NULL.
1227  *
1228  * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise and
1229  *         values are zeroed.
1230  */
1231 Eina_Bool
ewk_frame_scroll_size_get(const Evas_Object * o,int * w,int * h)1232 ewk_frame_scroll_size_get(const Evas_Object* o, int* w, int* h)
1233 {
1234     if (w)
1235         *w = 0;
1236     if (h)
1237         *h = 0;
1238     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1239     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1240     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame->view(), EINA_FALSE);
1241     WebCore::IntPoint point = sd->frame->view()->maximumScrollPosition();
1242     if (w)
1243         *w = point.x();
1244     if (h)
1245         *h = point.y();
1246     return EINA_TRUE;
1247 }
1248 
1249 /**
1250  * Get the current scroll position of given frame.
1251  *
1252  * @param o frame object to scroll.
1253  * @param x where to return horizontal position. May be @c NULL.
1254  * @param y where to return vertical position. May be @c NULL.
1255  *
1256  * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise and
1257  *         values are zeroed.
1258  */
1259 Eina_Bool
ewk_frame_scroll_pos_get(const Evas_Object * o,int * x,int * y)1260 ewk_frame_scroll_pos_get(const Evas_Object* o, int* x, int* y)
1261 {
1262     if (x)
1263         *x = 0;
1264     if (y)
1265         *y = 0;
1266     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1267     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1268     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame->view(), EINA_FALSE);
1269     WebCore::IntPoint pos = sd->frame->view()->scrollPosition();
1270     if (x)
1271         *x = pos.x();
1272     if (y)
1273         *y = pos.y();
1274     return EINA_TRUE;
1275 }
1276 
1277 /**
1278  * Get the current frame visible content geometry.
1279  *
1280  * @param o frame object to query visible content geometry.
1281  * @param include_scrollbars whenever to include scrollbars size.
1282  * @param x horizontal position. May be @c NULL.
1283  * @param y vertical position. May be @c NULL.
1284  * @param w width. May be @c NULL.
1285  * @param h height. May be @c NULL.
1286  *
1287  * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise and
1288  *         values are zeroed.
1289  */
ewk_frame_visible_content_geometry_get(const Evas_Object * o,Eina_Bool include_scrollbars,int * x,int * y,int * w,int * h)1290 Eina_Bool ewk_frame_visible_content_geometry_get(const Evas_Object* o, Eina_Bool include_scrollbars, int* x, int* y, int* w, int* h)
1291 {
1292     if (x)
1293         *x = 0;
1294     if (y)
1295         *y = 0;
1296     if (w)
1297         *w = 0;
1298     if (h)
1299         *h = 0;
1300     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1301     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1302     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame->view(), EINA_FALSE);
1303     WebCore::IntRect rect = sd->frame->view()->visibleContentRect(include_scrollbars);
1304     if (x)
1305         *x = rect.x();
1306     if (y)
1307         *y = rect.y();
1308     if (w)
1309         *w = rect.width();
1310     if (h)
1311         *h = rect.height();
1312     return EINA_TRUE;
1313 }
1314 
1315 /**
1316  * Get the current paintsEntireContents flag.
1317  *
1318  * This flag tells if dirty areas should be repainted even if they are
1319  * out of the screen.
1320  *
1321  * @param o frame object to query paintsEntireContents flag.
1322  *
1323  * @return @c EINA_TRUE if repainting any dirty area, @c EINA_FALSE
1324  *         otherwise.
1325  */
ewk_frame_paint_full_get(const Evas_Object * o)1326 Eina_Bool ewk_frame_paint_full_get(const Evas_Object* o)
1327 {
1328     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1329     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1330     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame->view(), EINA_FALSE);
1331     return sd->frame->view()->paintsEntireContents();
1332 }
1333 
1334 /**
1335  * Set the current paintsEntireContents flag.
1336  *
1337  * This flag tells if dirty areas should be repainted even if they are
1338  * out of the screen.
1339  *
1340  * @param o frame object to set paintsEntireContents flag.
1341  * @param flag @c EINA_TRUE if want to always repaint any dirty area,
1342  *             @c EINA_FALSE otherwise.
1343  */
ewk_frame_paint_full_set(Evas_Object * o,Eina_Bool flag)1344 void ewk_frame_paint_full_set(Evas_Object* o, Eina_Bool flag)
1345 {
1346     EWK_FRAME_SD_GET_OR_RETURN(o, sd);
1347     EINA_SAFETY_ON_NULL_RETURN(sd->frame);
1348     EINA_SAFETY_ON_NULL_RETURN(sd->frame->view());
1349     sd->frame->view()->setPaintsEntireContents(flag);
1350 }
1351 
1352 /**
1353  * Feed the focus in signal to this frame.
1354  *
1355  * @param o frame object to focus.
1356  *
1357  * @return @c EINA_TRUE if it was handled, @c EINA_FALSE otherwise.
1358  */
ewk_frame_feed_focus_in(Evas_Object * o)1359 Eina_Bool ewk_frame_feed_focus_in(Evas_Object* o)
1360 {
1361     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1362     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1363     WebCore::FocusController* c = sd->frame->page()->focusController();
1364     c->setFocusedFrame(sd->frame);
1365     return EINA_TRUE;
1366 }
1367 
1368 /**
1369  * Feed the focus out signal to this frame.
1370  *
1371  * @param o frame object to remove focus.
1372  */
ewk_frame_feed_focus_out(Evas_Object * o)1373 Eina_Bool ewk_frame_feed_focus_out(Evas_Object* o)
1374 {
1375     // TODO: what to do on focus out?
1376     ERR("what to do?");
1377     return EINA_FALSE;
1378 }
1379 
1380 /**
1381  * Feed the mouse wheel event to the frame.
1382  *
1383  * @param o frame object to feed event.
1384  * @param ev mouse wheel event.
1385  *
1386  * @return @c EINA_TRUE if it was handled, @c EINA_FALSE otherwise.
1387  */
ewk_frame_feed_mouse_wheel(Evas_Object * o,const Evas_Event_Mouse_Wheel * ev)1388 Eina_Bool ewk_frame_feed_mouse_wheel(Evas_Object* o, const Evas_Event_Mouse_Wheel* ev)
1389 {
1390     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1391     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1392     EINA_SAFETY_ON_NULL_RETURN_VAL(ev, EINA_FALSE);
1393 
1394     WebCore::FrameView* view = sd->frame->view();
1395     DBG("o=%p, view=%p, direction=%d, z=%d, pos=%d,%d",
1396         o, view, ev->direction, ev->z, ev->canvas.x, ev->canvas.y);
1397     EINA_SAFETY_ON_NULL_RETURN_VAL(view, EINA_FALSE);
1398 
1399     WebCore::PlatformWheelEvent event(ev);
1400     return sd->frame->eventHandler()->handleWheelEvent(event);
1401 }
1402 
1403 /**
1404  * Feed the mouse down event to the frame.
1405  *
1406  * @param o frame object to feed event.
1407  * @param ev mouse down event.
1408  *
1409  * @return @c EINA_TRUE if it was handled, @c EINA_FALSE otherwise.
1410  */
ewk_frame_feed_mouse_down(Evas_Object * o,const Evas_Event_Mouse_Down * ev)1411 Eina_Bool ewk_frame_feed_mouse_down(Evas_Object* o, const Evas_Event_Mouse_Down* ev)
1412 {
1413     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1414     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1415     EINA_SAFETY_ON_NULL_RETURN_VAL(ev, EINA_FALSE);
1416 
1417     WebCore::FrameView* view = sd->frame->view();
1418     DBG("o=%p, view=%p, button=%d, pos=%d,%d",
1419         o, view, ev->button, ev->canvas.x, ev->canvas.y);
1420     EINA_SAFETY_ON_NULL_RETURN_VAL(view, EINA_FALSE);
1421 
1422     Evas_Coord x, y;
1423     evas_object_geometry_get(sd->view, &x, &y, 0, 0);
1424 
1425     WebCore::PlatformMouseEvent event(ev, WebCore::IntPoint(x, y));
1426     return sd->frame->eventHandler()->handleMousePressEvent(event);
1427 }
1428 
1429 /**
1430  * Feed the mouse up event to the frame.
1431  *
1432  * @param o frame object to feed event.
1433  * @param ev mouse up event.
1434  *
1435  * @return @c EINA_TRUE if it was handled, @c EINA_FALSE otherwise.
1436  */
ewk_frame_feed_mouse_up(Evas_Object * o,const Evas_Event_Mouse_Up * ev)1437 Eina_Bool ewk_frame_feed_mouse_up(Evas_Object* o, const Evas_Event_Mouse_Up* ev)
1438 {
1439     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1440     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1441     EINA_SAFETY_ON_NULL_RETURN_VAL(ev, EINA_FALSE);
1442 
1443     WebCore::FrameView* view = sd->frame->view();
1444     DBG("o=%p, view=%p, button=%d, pos=%d,%d",
1445         o, view, ev->button, ev->canvas.x, ev->canvas.y);
1446     EINA_SAFETY_ON_NULL_RETURN_VAL(view, EINA_FALSE);
1447 
1448     Evas_Coord x, y;
1449     evas_object_geometry_get(sd->view, &x, &y, 0, 0);
1450 
1451     WebCore::PlatformMouseEvent event(ev, WebCore::IntPoint(x, y));
1452     return sd->frame->eventHandler()->handleMouseReleaseEvent(event);
1453 }
1454 
1455 /**
1456  * Feed the mouse move event to the frame.
1457  *
1458  * @param o frame object to feed event.
1459  * @param ev mouse move event.
1460  *
1461  * @return @c EINA_TRUE if it was handled, @c EINA_FALSE otherwise.
1462  */
ewk_frame_feed_mouse_move(Evas_Object * o,const Evas_Event_Mouse_Move * ev)1463 Eina_Bool ewk_frame_feed_mouse_move(Evas_Object* o, const Evas_Event_Mouse_Move* ev)
1464 {
1465     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1466     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1467     EINA_SAFETY_ON_NULL_RETURN_VAL(ev, EINA_FALSE);
1468 
1469     WebCore::FrameView* view = sd->frame->view();
1470     DBG("o=%p, view=%p, pos: old=%d,%d, new=%d,%d, buttons=%d",
1471         o, view, ev->cur.canvas.x, ev->cur.canvas.y,
1472         ev->prev.canvas.x, ev->prev.canvas.y, ev->buttons);
1473     EINA_SAFETY_ON_NULL_RETURN_VAL(view, EINA_FALSE);
1474 
1475     Evas_Coord x, y;
1476     evas_object_geometry_get(sd->view, &x, &y, 0, 0);
1477 
1478     WebCore::PlatformMouseEvent event(ev, WebCore::IntPoint(x, y));
1479     return sd->frame->eventHandler()->mouseMoved(event);
1480 }
1481 
ewk_frame_feed_touch_event(Evas_Object * o,Ewk_Touch_Event_Type action,Eina_List * points,int metaState)1482 Eina_Bool ewk_frame_feed_touch_event(Evas_Object* o, Ewk_Touch_Event_Type action, Eina_List* points, int metaState)
1483 {
1484     Eina_Bool ret = EINA_FALSE;
1485 
1486 #if ENABLE(TOUCH_EVENTS)
1487     EINA_SAFETY_ON_NULL_RETURN_VAL(points, EINA_FALSE);
1488     EWK_FRAME_SD_GET(o, sd);
1489 
1490     if (!sd || !sd->frame || !ewk_view_need_touch_events_get(sd->view)) {
1491         void* point;
1492         EINA_LIST_FREE(points, point);
1493         return EINA_FALSE;
1494     }
1495 
1496     Evas_Coord x, y;
1497     evas_object_geometry_get(sd->view, &x, &y, 0, 0);
1498 
1499     WebCore::TouchEventType type = WebCore::TouchStart;
1500     switch (action) {
1501     case EWK_TOUCH_START:
1502         type = WebCore::TouchStart;
1503         break;
1504     case EWK_TOUCH_END:
1505         type = WebCore::TouchEnd;
1506         break;
1507     case EWK_TOUCH_MOVE:
1508         type = WebCore::TouchMove;
1509         break;
1510     case EWK_TOUCH_CANCEL:
1511         type = WebCore::TouchCancel;
1512         break;
1513     default:
1514         return EINA_FALSE;
1515     }
1516 
1517     WebCore::PlatformTouchEvent te(points, WebCore::IntPoint(x, y), type, metaState);
1518     ret = sd->frame->eventHandler()->handleTouchEvent(te);
1519 #endif
1520     return ret;
1521 }
1522 
_ewk_frame_handle_key_scrolling(WebCore::Frame * frame,const WebCore::PlatformKeyboardEvent & event)1523 static inline Eina_Bool _ewk_frame_handle_key_scrolling(WebCore::Frame* frame, const WebCore::PlatformKeyboardEvent &event)
1524 {
1525     WebCore::ScrollDirection direction;
1526     WebCore::ScrollGranularity granularity;
1527 
1528     int keyCode = event.windowsVirtualKeyCode();
1529 
1530     switch (keyCode) {
1531     case VK_SPACE:
1532         granularity = WebCore::ScrollByPage;
1533         if (event.shiftKey())
1534             direction = WebCore::ScrollUp;
1535         else
1536             direction = WebCore::ScrollDown;
1537         break;
1538     case VK_NEXT:
1539         granularity = WebCore::ScrollByPage;
1540         direction = WebCore::ScrollDown;
1541         break;
1542     case VK_PRIOR:
1543         granularity = WebCore::ScrollByPage;
1544         direction = WebCore::ScrollUp;
1545         break;
1546     case VK_HOME:
1547         granularity = WebCore::ScrollByDocument;
1548         direction = WebCore::ScrollUp;
1549         break;
1550     case VK_END:
1551         granularity = WebCore::ScrollByDocument;
1552         direction = WebCore::ScrollDown;
1553         break;
1554     case VK_LEFT:
1555         granularity = WebCore::ScrollByLine;
1556         direction = WebCore::ScrollLeft;
1557         break;
1558     case VK_RIGHT:
1559         granularity = WebCore::ScrollByLine;
1560         direction = WebCore::ScrollRight;
1561         break;
1562     case VK_UP:
1563         direction = WebCore::ScrollUp;
1564         if (event.ctrlKey())
1565             granularity = WebCore::ScrollByDocument;
1566         else
1567             granularity = WebCore::ScrollByLine;
1568         break;
1569     case VK_DOWN:
1570         direction = WebCore::ScrollDown;
1571          if (event.ctrlKey())
1572             granularity = WebCore::ScrollByDocument;
1573         else
1574             granularity = WebCore::ScrollByLine;
1575         break;
1576     default:
1577         return EINA_FALSE;
1578     }
1579 
1580     if (frame->eventHandler()->scrollOverflow(direction, granularity))
1581         return EINA_FALSE;
1582 
1583     frame->view()->scroll(direction, granularity);
1584     return EINA_TRUE;
1585 }
1586 
1587 /**
1588  * Feed the keyboard key down event to the frame.
1589  *
1590  * @param o frame object to feed event.
1591  * @param ev keyboard key down event.
1592  *
1593  * @return @c EINA_TRUE if it was handled, @c EINA_FALSE otherwise.
1594  */
ewk_frame_feed_key_down(Evas_Object * o,const Evas_Event_Key_Down * ev)1595 Eina_Bool ewk_frame_feed_key_down(Evas_Object* o, const Evas_Event_Key_Down* ev)
1596 {
1597     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1598     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1599     EINA_SAFETY_ON_NULL_RETURN_VAL(ev, EINA_FALSE);
1600 
1601     DBG("o=%p keyname=%s (key=%s, string=%s)",
1602         o, ev->keyname, ev->key ? ev->key : "", ev->string ? ev->string : "");
1603 
1604     WebCore::PlatformKeyboardEvent event(ev);
1605     if (sd->frame->eventHandler()->keyEvent(event))
1606         return EINA_TRUE;
1607 
1608     return _ewk_frame_handle_key_scrolling(sd->frame, event);
1609 }
1610 
1611 /**
1612  * Feed the keyboard key up event to the frame.
1613  *
1614  * @param o frame object to feed event.
1615  * @param ev keyboard key up event.
1616  *
1617  * @return @c EINA_TRUE if it was handled, @c EINA_FALSE otherwise.
1618  */
ewk_frame_feed_key_up(Evas_Object * o,const Evas_Event_Key_Up * ev)1619 Eina_Bool ewk_frame_feed_key_up(Evas_Object* o, const Evas_Event_Key_Up* ev)
1620 {
1621     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1622     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1623     EINA_SAFETY_ON_NULL_RETURN_VAL(ev, EINA_FALSE);
1624 
1625     DBG("o=%p keyname=%s (key=%s, string=%s)",
1626         o, ev->keyname, ev->key ? ev->key : "", ev->string ? ev->string : "");
1627 
1628     WebCore::PlatformKeyboardEvent event(ev);
1629     return sd->frame->eventHandler()->keyEvent(event);
1630 }
1631 
1632 /* internal methods ****************************************************/
1633 
1634 /**
1635  * @internal
1636  *
1637  * Initialize frame based on actual WebKit frame.
1638  *
1639  * This is internal and should never be called by external users.
1640  */
ewk_frame_init(Evas_Object * o,Evas_Object * view,WebCore::Frame * frame)1641 Eina_Bool ewk_frame_init(Evas_Object* o, Evas_Object* view, WebCore::Frame* frame)
1642 {
1643     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1644     if (!sd->frame) {
1645         WebCore::FrameLoaderClientEfl* flc = _ewk_frame_loader_efl_get(frame);
1646         flc->setWebFrame(o);
1647         sd->frame = frame;
1648         sd->view = view;
1649         frame->init();
1650         return EINA_TRUE;
1651     }
1652 
1653     ERR("frame %p already set for %p, ignored new %p",
1654         sd->frame, o, frame);
1655     return EINA_FALSE;
1656 }
1657 
ewk_frame_child_add(Evas_Object * o,WTF::PassRefPtr<WebCore::Frame> child,const WTF::String & name,const WebCore::KURL & url,const WTF::String & referrer)1658 Evas_Object* ewk_frame_child_add(Evas_Object* o, WTF::PassRefPtr<WebCore::Frame> child, const WTF::String& name, const WebCore::KURL& url, const WTF::String& referrer)
1659 {
1660     EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
1661     char buf[256];
1662     Evas_Object* frame;
1663     WebCore::Frame* cf;
1664 
1665     frame = ewk_frame_add(sd->base.evas);
1666     if (!frame) {
1667         ERR("Could not create ewk_frame object.");
1668         return 0;
1669     }
1670 
1671     cf = child.get();
1672     if (cf->tree())
1673         cf->tree()->setName(name);
1674     else
1675         ERR("no tree for child object");
1676     sd->frame->tree()->appendChild(child);
1677 
1678     if (!ewk_frame_init(frame, sd->view, cf)) {
1679         evas_object_del(frame);
1680         return 0;
1681     }
1682     snprintf(buf, sizeof(buf), "EWK_Frame:child/%s", name.utf8().data());
1683     evas_object_name_set(frame, buf);
1684     evas_object_smart_member_add(frame, o);
1685     evas_object_show(frame);
1686 
1687     if (!cf->page())
1688         goto died;
1689 
1690     sd->frame->loader()->loadURLIntoChildFrame(url, referrer, cf);
1691     if (!cf->tree()->parent())
1692         goto died;
1693 
1694     // TODO: announce frame was created?
1695     return frame;
1696 
1697 died:
1698     CRITICAL("does this work: BEGIN");
1699     ewk_frame_core_gone(frame); // CONFIRM
1700     evas_object_del(frame); // CONFIRM
1701     CRITICAL("does this work: END");
1702     return 0;
1703 }
1704 
1705 /**
1706  * @internal
1707  * Frame was destroyed by loader, remove internal reference.
1708  */
ewk_frame_core_gone(Evas_Object * o)1709 void ewk_frame_core_gone(Evas_Object* o)
1710 {
1711     DBG("o=%p", o);
1712     EWK_FRAME_SD_GET_OR_RETURN(o, sd);
1713     sd->frame = 0;
1714 }
1715 
1716 /**
1717  * @internal
1718  * Retrieve WebCore::Frame associated with this object.
1719  *
1720  * Avoid using this call from outside, add specific ewk_frame_*
1721  * actions instead.
1722  */
ewk_frame_core_get(const Evas_Object * o)1723 WebCore::Frame* ewk_frame_core_get(const Evas_Object* o)
1724 {
1725     EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
1726     return sd->frame;
1727 }
1728 
1729 
1730 /**
1731  * @internal
1732  * Reports a resource will be requested. User may override behavior of webkit by
1733  * changing values in @param request.
1734  *
1735  * @param o Frame.
1736  * @param request Request details that user may override. Whenever values on
1737  * this struct changes, it must be properly malloc'd as it will be freed
1738  * afterwards.
1739  *
1740  * Emits signal: "resource,request,willsend"
1741  */
ewk_frame_request_will_send(Evas_Object * o,Ewk_Frame_Resource_Request * request)1742 void ewk_frame_request_will_send(Evas_Object *o, Ewk_Frame_Resource_Request *request)
1743 {
1744     evas_object_smart_callback_call(o, "resource,request,willsend", request);
1745 }
1746 
1747 /**
1748  * @internal
1749  * Reports that there's a new resource.
1750  *
1751  * @param o Frame.
1752  * @param request New request details. No changes are allowed to fields.
1753  *
1754  * Emits signal: "resource,request,new"
1755  */
ewk_frame_request_assign_identifier(Evas_Object * o,const Ewk_Frame_Resource_Request * request)1756 void ewk_frame_request_assign_identifier(Evas_Object *o, const Ewk_Frame_Resource_Request *request)
1757 {
1758     evas_object_smart_callback_call(o, "resource,request,new", (void *)request);
1759 }
1760 
1761 /**
1762  * @internal
1763  * Reports that first navigation occurred
1764  *
1765  * @param o Frame.
1766  *
1767  * Emits signal: "navigation,first"
1768  */
ewk_frame_did_perform_first_navigation(Evas_Object * o)1769 void ewk_frame_did_perform_first_navigation(Evas_Object *o)
1770 {
1771     evas_object_smart_callback_call(o, "navigation,first", 0);
1772 }
1773 
1774 /**
1775  * @internal
1776  * Reports frame will be saved to current state
1777  *
1778  * @param o Frame.
1779  * @param item History item to save details to.
1780  *
1781  * Emits signal: "state,save"
1782  */
ewk_frame_view_state_save(Evas_Object * o,WebCore::HistoryItem * item)1783 void ewk_frame_view_state_save(Evas_Object *o, WebCore::HistoryItem* item)
1784 {
1785     evas_object_smart_callback_call(o, "state,save", 0);
1786 }
1787 
1788 /**
1789  * @internal
1790  * Reports the frame started loading something.
1791  *
1792  * Emits signal: "load,started" with no parameters.
1793  */
ewk_frame_load_started(Evas_Object * o)1794 void ewk_frame_load_started(Evas_Object* o)
1795 {
1796     Evas_Object* main_frame;
1797     DBG("o=%p", o);
1798     evas_object_smart_callback_call(o, "load,started", 0);
1799     EWK_FRAME_SD_GET_OR_RETURN(o, sd);
1800     ewk_view_load_started(sd->view);
1801 
1802     main_frame = ewk_view_frame_main_get(sd->view);
1803     if (main_frame == o)
1804         ewk_view_frame_main_load_started(sd->view);
1805 }
1806 
1807 /**
1808  * @internal
1809  * Reports the frame started provisional load.
1810  *
1811  * @param o Frame.
1812  *
1813  * Emits signal: "load,provisional" with no parameters.
1814  */
ewk_frame_load_provisional(Evas_Object * o)1815 void ewk_frame_load_provisional(Evas_Object* o)
1816 {
1817     evas_object_smart_callback_call(o, "load,provisional", 0);
1818 }
1819 
1820 /**
1821  * @internal
1822  * Reports the frame finished first layout.
1823  *
1824  * @param o Frame.
1825  *
1826  * Emits signal: "load,firstlayout,finished" with no parameters.
1827  */
ewk_frame_load_firstlayout_finished(Evas_Object * o)1828 void ewk_frame_load_firstlayout_finished(Evas_Object *o)
1829 {
1830     evas_object_smart_callback_call(o, "load,firstlayout,finished", 0);
1831 }
1832 
1833 /**
1834  * @internal
1835  * Reports the frame finished first non empty layout.
1836  *
1837  * @param o Frame.
1838  *
1839  * Emits signal: "load,nonemptylayout,finished" with no parameters.
1840  */
ewk_frame_load_firstlayout_nonempty_finished(Evas_Object * o)1841 void ewk_frame_load_firstlayout_nonempty_finished(Evas_Object *o)
1842 {
1843     evas_object_smart_callback_call(o, "load,nonemptylayout,finished", 0);
1844 }
1845 
1846 /**
1847  * @internal
1848  * Reports the loading of a document has finished on frame.
1849  *
1850  * @param o Frame.
1851  *
1852  * Emits signal: "load,document,finished" with no parameters.
1853  */
ewk_frame_load_document_finished(Evas_Object * o)1854 void ewk_frame_load_document_finished(Evas_Object *o)
1855 {
1856     evas_object_smart_callback_call(o, "load,document,finished", 0);
1857 }
1858 
1859 /**
1860  * @internal
1861  * Reports load finished, optionally with error information.
1862  *
1863  * Emits signal: "load,finished" with pointer to Ewk_Frame_Load_Error
1864  * if any error, or @c NULL if successful load.
1865  *
1866  * @note there should notbe any error stuff here, but trying to be
1867  *       compatible with previous WebKit.
1868  */
ewk_frame_load_finished(Evas_Object * o,const char * error_domain,int error_code,Eina_Bool is_cancellation,const char * error_description,const char * failing_url)1869 void ewk_frame_load_finished(Evas_Object* o, const char* error_domain, int error_code, Eina_Bool is_cancellation, const char* error_description, const char* failing_url)
1870 {
1871     Ewk_Frame_Load_Error buf, *error;
1872     if (!error_domain) {
1873         DBG("o=%p, success.", o);
1874         error = 0;
1875     } else {
1876         DBG("o=%p, error=%s (%d, cancellation=%hhu) \"%s\", url=%s",
1877             o, error_domain, error_code, is_cancellation,
1878             error_description, failing_url);
1879 
1880         buf.domain = error_domain;
1881         buf.code = error_code;
1882         buf.is_cancellation = is_cancellation;
1883         buf.description = error_description;
1884         buf.failing_url = failing_url;
1885         buf.frame = o;
1886         error = &buf;
1887     }
1888     evas_object_smart_callback_call(o, "load,finished", error);
1889     EWK_FRAME_SD_GET_OR_RETURN(o, sd);
1890     ewk_view_load_finished(sd->view, error);
1891 }
1892 
1893 /**
1894  * @internal
1895  * Reports load failed with error information.
1896  *
1897  * Emits signal: "load,error" with pointer to Ewk_Frame_Load_Error.
1898  */
ewk_frame_load_error(Evas_Object * o,const char * error_domain,int error_code,Eina_Bool is_cancellation,const char * error_description,const char * failing_url)1899 void ewk_frame_load_error(Evas_Object* o, const char* error_domain, int error_code, Eina_Bool is_cancellation, const char* error_description, const char* failing_url)
1900 {
1901     Ewk_Frame_Load_Error error;
1902 
1903     DBG("o=%p, error=%s (%d, cancellation=%hhu) \"%s\", url=%s",
1904         o, error_domain, error_code, is_cancellation,
1905         error_description, failing_url);
1906 
1907     EINA_SAFETY_ON_NULL_RETURN(error_domain);
1908 
1909     error.code = error_code;
1910     error.is_cancellation = is_cancellation;
1911     error.domain = error_domain;
1912     error.description = error_description;
1913     error.failing_url = failing_url;
1914     error.frame = o;
1915     evas_object_smart_callback_call(o, "load,error", &error);
1916     EWK_FRAME_SD_GET_OR_RETURN(o, sd);
1917     ewk_view_load_error(sd->view, &error);
1918 }
1919 
1920 /**
1921  * @internal
1922  * Reports load progress changed.
1923  *
1924  * Emits signal: "load,progress" with pointer to a double from 0.0 to 1.0.
1925  */
ewk_frame_load_progress_changed(Evas_Object * o)1926 void ewk_frame_load_progress_changed(Evas_Object* o)
1927 {
1928     EWK_FRAME_SD_GET_OR_RETURN(o, sd);
1929     EINA_SAFETY_ON_NULL_RETURN(sd->frame);
1930 
1931     // TODO: this is per page, there should be a way to have per-frame.
1932     double progress = sd->frame->page()->progress()->estimatedProgress();
1933 
1934     DBG("o=%p (p=%0.3f)", o, progress);
1935 
1936     evas_object_smart_callback_call(o, "load,progress", &progress);
1937     ewk_view_load_progress_changed(sd->view);
1938 }
1939 
1940 
1941 /**
1942  * @internal
1943  *
1944  * Reports contents size changed.
1945  */
ewk_frame_contents_size_changed(Evas_Object * o,Evas_Coord w,Evas_Coord h)1946 void ewk_frame_contents_size_changed(Evas_Object* o, Evas_Coord w, Evas_Coord h)
1947 {
1948     DBG("o=%p: %dx%d", o, w, h);
1949     EWK_FRAME_SD_GET_OR_RETURN(o, sd);
1950     if (sd->contents_size.w == w && sd->contents_size.h == h)
1951         return;
1952     sd->contents_size.w = w;
1953     sd->contents_size.h = h;
1954     // TODO: update something else internally?
1955 
1956     Evas_Coord size[2] = {w, h};
1957     evas_object_smart_callback_call(o, "contents,size,changed", size);
1958 }
1959 
1960 /**
1961  * @internal
1962  *
1963  * Reports title changed.
1964  */
ewk_frame_title_set(Evas_Object * o,const char * title)1965 void ewk_frame_title_set(Evas_Object* o, const char* title)
1966 {
1967     DBG("o=%p, title=%s", o, title ? title : "(null)");
1968     EWK_FRAME_SD_GET_OR_RETURN(o, sd);
1969     if (!eina_stringshare_replace(&sd->title, title))
1970         return;
1971     evas_object_smart_callback_call(o, "title,changed", (void*)sd->title);
1972 }
1973 
ewk_frame_view_create_for_view(Evas_Object * o,Evas_Object * view)1974 void ewk_frame_view_create_for_view(Evas_Object* o, Evas_Object* view)
1975 {
1976     DBG("o=%p, view=%p", o, view);
1977     EWK_FRAME_SD_GET_OR_RETURN(o, sd);
1978     EINA_SAFETY_ON_NULL_RETURN(sd->frame);
1979     Evas_Coord w, h;
1980 
1981     if (sd->frame->view())
1982         return;
1983 
1984     evas_object_geometry_get(view, 0, 0, &w, &h);
1985 
1986     WebCore::IntSize size(w, h);
1987     int r, g, b, a;
1988     WebCore::Color bg;
1989 
1990     ewk_view_bg_color_get(view, &r, &g, &b, &a);
1991     if (!a)
1992         bg = WebCore::Color(0, 0, 0, 0);
1993     else if (a == 255)
1994         bg = WebCore::Color(r, g, b, a);
1995     else
1996         bg = WebCore::Color(r * 255 / a, g * 255 / a, b * 255 / a, a);
1997 
1998     sd->frame->createView(size, bg, !a, WebCore::IntSize(), false);
1999     if (!sd->frame->view())
2000         return;
2001 
2002     const char* theme = ewk_view_theme_get(view);
2003     sd->frame->view()->setEdjeTheme(theme);
2004     sd->frame->view()->setEvasObject(o);
2005 }
2006 
2007 /**
2008  * @internal
2009  * Reports uri changed and swap internal string reference.
2010  *
2011  * Emits signal: "uri,changed" with new uri as parameter.
2012  */
ewk_frame_uri_changed(Evas_Object * o)2013 Eina_Bool ewk_frame_uri_changed(Evas_Object* o)
2014 {
2015     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2016     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
2017     WTF::CString uri(sd->frame->document()->url().prettyURL().utf8());
2018 
2019     INF("uri=%s", uri.data());
2020     if (!uri.data()) {
2021         ERR("no uri");
2022         return EINA_FALSE;
2023     }
2024 
2025     eina_stringshare_replace(&sd->uri, uri.data());
2026     evas_object_smart_callback_call(o, "uri,changed", (void*)sd->uri);
2027     return EINA_TRUE;
2028 }
2029 
ewk_frame_force_layout(Evas_Object * o)2030 void ewk_frame_force_layout(Evas_Object* o)
2031 {
2032     DBG("o=%p", o);
2033     EWK_FRAME_SD_GET_OR_RETURN(o, sd);
2034     EINA_SAFETY_ON_NULL_RETURN(sd->frame);
2035     WebCore::FrameView* view = sd->frame->view();
2036     if (view)
2037         view->forceLayout(true);
2038 }
2039 
ewk_frame_plugin_create(Evas_Object * o,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)2040 WTF::PassRefPtr<WebCore::Widget> ewk_frame_plugin_create(Evas_Object* o, 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)
2041 {
2042     return 0;
2043 }
2044