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