Home | History | Annotate | Download | only in ewk
      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
    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 
    141 static WebCore::FrameLoaderClientEfl* _ewk_frame_loader_efl_get(WebCore::Frame* frame)
    142 {
    143     return static_cast<WebCore::FrameLoaderClientEfl*>(frame->loader()->client());
    144 }
    145 
    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 
    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 
    177 static Evas_Object* _ewk_frame_children_iterator_get_container(Eina_Iterator_Ewk_Frame* it)
    178 {
    179     return it->obj;
    180 }
    181 
    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 
    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 
    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 
    274 static void _ewk_frame_smart_set(Evas_Smart_Class* api)
    275 {
    276     evas_object_smart_clipped_smart_set(api);
    277     api->add = _ewk_frame_smart_add;
    278     api->del = _ewk_frame_smart_del;
    279     api->resize = _ewk_frame_smart_resize;
    280 }
    281 
    282 static inline Evas_Smart* _ewk_frame_smart_class_new(void)
    283 {
    284     static Evas_Smart_Class 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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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 
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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 
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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().string().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
   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
   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
   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
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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 
   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 
   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  */
   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  */
   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  */
   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 
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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 
   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  */
   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().string().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 
   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 
   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