1 /* 2 * Copyright (C) 2006 Zack Rusin <zack@kde.org> 3 * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. 4 * Copyright (C) 2008 Kenneth Rohde Christiansen 5 * Copyright (C) 2008 Diego Gonzalez 6 * Copyright (C) 2009-2010 ProFUSION embedded systems 7 * Copyright (C) 2009-2010 Samsung Electronics 8 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 9 * 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 29 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "config.h" 35 #include "ChromeClientEfl.h" 36 37 #if ENABLE(DATABASE) 38 #include "DatabaseDetails.h" 39 #include "DatabaseTracker.h" 40 #endif 41 #include "EWebKit.h" 42 #include "FileChooser.h" 43 #include "FloatRect.h" 44 #include "FrameLoader.h" 45 #include "FrameLoaderClientEfl.h" 46 #include "HitTestResult.h" 47 #include "IntRect.h" 48 #include "KURL.h" 49 #include "NavigationAction.h" 50 #include "NotImplemented.h" 51 #include "PlatformString.h" 52 #include "SecurityOrigin.h" 53 #include "PopupMenuEfl.h" 54 #include "SearchPopupMenuEfl.h" 55 #include "ViewportArguments.h" 56 #include "WindowFeatures.h" 57 #include "ewk_private.h" 58 #include <Ecore_Evas.h> 59 #include <Evas.h> 60 #include <wtf/text/CString.h> 61 62 using namespace WebCore; 63 kit(Frame * frame)64 static inline Evas_Object* kit(Frame* frame) 65 { 66 if (!frame) 67 return 0; 68 69 FrameLoaderClientEfl* client = static_cast<FrameLoaderClientEfl*>(frame->loader()->client()); 70 return client ? client->webFrame() : 0; 71 } 72 73 namespace WebCore { 74 ChromeClientEfl(Evas_Object * view)75 ChromeClientEfl::ChromeClientEfl(Evas_Object* view) 76 : m_view(view) 77 { 78 } 79 ~ChromeClientEfl()80 ChromeClientEfl::~ChromeClientEfl() 81 { 82 } 83 chromeDestroyed()84 void ChromeClientEfl::chromeDestroyed() 85 { 86 delete this; 87 } 88 focusedNodeChanged(Node *)89 void ChromeClientEfl::focusedNodeChanged(Node*) 90 { 91 notImplemented(); 92 } 93 focusedFrameChanged(Frame *)94 void ChromeClientEfl::focusedFrameChanged(Frame*) 95 { 96 } 97 windowRect()98 FloatRect ChromeClientEfl::windowRect() 99 { 100 Ecore_Evas* ee = 0; 101 int x, y, w, h; 102 103 if (!m_view) 104 return FloatRect(); 105 106 ee = ecore_evas_ecore_evas_get(evas_object_evas_get(m_view)); 107 ecore_evas_geometry_get(ee, &x, &y, &w, &h); 108 return FloatRect(x, y, w, h); 109 } 110 setWindowRect(const FloatRect & rect)111 void ChromeClientEfl::setWindowRect(const FloatRect& rect) 112 { 113 Ecore_Evas* ee = 0; 114 IntRect intrect = IntRect(rect); 115 116 if (!m_view) 117 return; 118 119 if (!ewk_view_setting_enable_auto_resize_window_get(m_view)) 120 return; 121 122 ee = ecore_evas_ecore_evas_get(evas_object_evas_get(m_view)); 123 ecore_evas_move(ee, intrect.x(), intrect.y()); 124 ecore_evas_resize(ee, intrect.width(), intrect.height()); 125 } 126 pageRect()127 FloatRect ChromeClientEfl::pageRect() 128 { 129 if (!m_view) 130 return FloatRect(); 131 132 return ewk_view_page_rect_get(m_view); 133 } 134 scaleFactor()135 float ChromeClientEfl::scaleFactor() 136 { 137 notImplemented(); 138 return 1.0; 139 } 140 focus()141 void ChromeClientEfl::focus() 142 { 143 evas_object_focus_set(m_view, EINA_TRUE); 144 } 145 unfocus()146 void ChromeClientEfl::unfocus() 147 { 148 evas_object_focus_set(m_view, EINA_FALSE); 149 } 150 createWindow(Frame *,const FrameLoadRequest & frameLoadRequest,const WindowFeatures & features,const NavigationAction &)151 Page* ChromeClientEfl::createWindow(Frame*, const FrameLoadRequest& frameLoadRequest, const WindowFeatures& features, const NavigationAction&) 152 { 153 Evas_Object* newView = ewk_view_window_create(m_view, EINA_TRUE, &features); 154 if (!newView) 155 return 0; 156 157 return ewk_view_core_page_get(newView); 158 } 159 show()160 void ChromeClientEfl::show() 161 { 162 ewk_view_ready(m_view); 163 } 164 canRunModal()165 bool ChromeClientEfl::canRunModal() 166 { 167 notImplemented(); 168 return false; 169 } 170 runModal()171 void ChromeClientEfl::runModal() 172 { 173 notImplemented(); 174 } 175 setToolbarsVisible(bool visible)176 void ChromeClientEfl::setToolbarsVisible(bool visible) 177 { 178 ewk_view_toolbars_visible_set(m_view, visible); 179 } 180 toolbarsVisible()181 bool ChromeClientEfl::toolbarsVisible() 182 { 183 Eina_Bool visible; 184 185 ewk_view_toolbars_visible_get(m_view, &visible); 186 return visible; 187 } 188 setStatusbarVisible(bool visible)189 void ChromeClientEfl::setStatusbarVisible(bool visible) 190 { 191 ewk_view_statusbar_visible_set(m_view, visible); 192 } 193 statusbarVisible()194 bool ChromeClientEfl::statusbarVisible() 195 { 196 Eina_Bool visible; 197 198 ewk_view_statusbar_visible_get(m_view, &visible); 199 return visible; 200 } 201 setScrollbarsVisible(bool visible)202 void ChromeClientEfl::setScrollbarsVisible(bool visible) 203 { 204 ewk_view_scrollbars_visible_set(m_view, visible); 205 } 206 scrollbarsVisible()207 bool ChromeClientEfl::scrollbarsVisible() 208 { 209 Eina_Bool visible; 210 211 ewk_view_scrollbars_visible_get(m_view, &visible); 212 return visible; 213 } 214 setMenubarVisible(bool visible)215 void ChromeClientEfl::setMenubarVisible(bool visible) 216 { 217 ewk_view_menubar_visible_set(m_view, visible); 218 } 219 menubarVisible()220 bool ChromeClientEfl::menubarVisible() 221 { 222 Eina_Bool visible; 223 224 ewk_view_menubar_visible_get(m_view, &visible); 225 return visible; 226 } 227 createSelectPopup(PopupMenuClient * client,int selected,const IntRect & rect)228 void ChromeClientEfl::createSelectPopup(PopupMenuClient* client, int selected, const IntRect& rect) 229 { 230 ewk_view_popup_new(m_view, client, selected, rect); 231 } 232 destroySelectPopup()233 bool ChromeClientEfl::destroySelectPopup() 234 { 235 return ewk_view_popup_destroy(m_view); 236 } 237 setResizable(bool)238 void ChromeClientEfl::setResizable(bool) 239 { 240 notImplemented(); 241 } 242 closeWindowSoon()243 void ChromeClientEfl::closeWindowSoon() 244 { 245 ewk_view_window_close(m_view); 246 } 247 canTakeFocus(FocusDirection)248 bool ChromeClientEfl::canTakeFocus(FocusDirection) 249 { 250 // This is called when cycling through links/focusable objects and we 251 // reach the last focusable object. 252 return false; 253 } 254 takeFocus(FocusDirection)255 void ChromeClientEfl::takeFocus(FocusDirection) 256 { 257 unfocus(); 258 } 259 canRunBeforeUnloadConfirmPanel()260 bool ChromeClientEfl::canRunBeforeUnloadConfirmPanel() 261 { 262 return true; 263 } 264 runBeforeUnloadConfirmPanel(const String & message,Frame * frame)265 bool ChromeClientEfl::runBeforeUnloadConfirmPanel(const String& message, Frame* frame) 266 { 267 return runJavaScriptConfirm(frame, message); 268 } 269 addMessageToConsole(MessageSource,MessageType,MessageLevel,const String & message,unsigned int lineNumber,const String & sourceID)270 void ChromeClientEfl::addMessageToConsole(MessageSource, MessageType, MessageLevel, const String& message, 271 unsigned int lineNumber, const String& sourceID) 272 { 273 ewk_view_add_console_message(m_view, message.utf8().data(), lineNumber, sourceID.utf8().data()); 274 } 275 runJavaScriptAlert(Frame * frame,const String & message)276 void ChromeClientEfl::runJavaScriptAlert(Frame* frame, const String& message) 277 { 278 ewk_view_run_javascript_alert(m_view, kit(frame), message.utf8().data()); 279 } 280 runJavaScriptConfirm(Frame * frame,const String & message)281 bool ChromeClientEfl::runJavaScriptConfirm(Frame* frame, const String& message) 282 { 283 return ewk_view_run_javascript_confirm(m_view, kit(frame), message.utf8().data()); 284 } 285 runJavaScriptPrompt(Frame * frame,const String & message,const String & defaultValue,String & result)286 bool ChromeClientEfl::runJavaScriptPrompt(Frame* frame, const String& message, const String& defaultValue, String& result) 287 { 288 char* value = 0; 289 ewk_view_run_javascript_prompt(m_view, kit(frame), message.utf8().data(), defaultValue.utf8().data(), &value); 290 if (value) { 291 result = String::fromUTF8(value); 292 free(value); 293 return true; 294 } 295 return false; 296 } 297 setStatusbarText(const String & string)298 void ChromeClientEfl::setStatusbarText(const String& string) 299 { 300 ewk_view_statusbar_text_set(m_view, string.utf8().data()); 301 } 302 shouldInterruptJavaScript()303 bool ChromeClientEfl::shouldInterruptJavaScript() 304 { 305 return ewk_view_should_interrupt_javascript(m_view); 306 } 307 keyboardUIMode()308 KeyboardUIMode ChromeClientEfl::keyboardUIMode() 309 { 310 return KeyboardAccessTabsToLinks; 311 } 312 windowResizerRect() const313 IntRect ChromeClientEfl::windowResizerRect() const 314 { 315 notImplemented(); 316 // Implementing this function will make repaint being 317 // called during resize, but as this will be done with 318 // a minor delay it adds a weird "filling" effect due 319 // to us using an evas image for showing the cairo 320 // context. So instead of implementing this function 321 // we call paint directly during resize with 322 // the new object size as its argument. 323 return IntRect(); 324 } 325 contentsSizeChanged(Frame * frame,const IntSize & size) const326 void ChromeClientEfl::contentsSizeChanged(Frame* frame, const IntSize& size) const 327 { 328 ewk_frame_contents_size_changed(kit(frame), size.width(), size.height()); 329 if (ewk_view_frame_main_get(m_view) == kit(frame)) 330 ewk_view_contents_size_changed(m_view, size.width(), size.height()); 331 } 332 windowToScreen(const IntRect & rect) const333 IntRect ChromeClientEfl::windowToScreen(const IntRect& rect) const 334 { 335 notImplemented(); 336 return rect; 337 } 338 screenToWindow(const IntPoint & point) const339 IntPoint ChromeClientEfl::screenToWindow(const IntPoint& point) const 340 { 341 notImplemented(); 342 return point; 343 } 344 platformPageClient() const345 PlatformPageClient ChromeClientEfl::platformPageClient() const 346 { 347 return m_view; 348 } 349 scrollbarsModeDidChange() const350 void ChromeClientEfl::scrollbarsModeDidChange() const 351 { 352 } 353 mouseDidMoveOverElement(const HitTestResult & hit,unsigned modifierFlags)354 void ChromeClientEfl::mouseDidMoveOverElement(const HitTestResult& hit, unsigned modifierFlags) 355 { 356 // FIXME, compare with old link, look at Qt impl. 357 bool isLink = hit.isLiveLink(); 358 if (isLink) { 359 KURL url = hit.absoluteLinkURL(); 360 if (!url.isEmpty() && url != m_hoveredLinkURL) { 361 const char* link[2]; 362 TextDirection dir; 363 CString urlStr = url.string().utf8(); 364 CString titleStr = hit.title(dir).utf8(); 365 link[0] = urlStr.data(); 366 link[1] = titleStr.data(); 367 ewk_view_mouse_link_hover_in(m_view, link); 368 m_hoveredLinkURL = url; 369 } 370 } else if (!isLink && !m_hoveredLinkURL.isEmpty()) { 371 ewk_view_mouse_link_hover_out(m_view); 372 m_hoveredLinkURL = KURL(); 373 } 374 } 375 setToolTip(const String & toolTip,TextDirection)376 void ChromeClientEfl::setToolTip(const String& toolTip, TextDirection) 377 { 378 ewk_view_tooltip_text_set(m_view, toolTip.utf8().data()); 379 } 380 print(Frame * frame)381 void ChromeClientEfl::print(Frame* frame) 382 { 383 notImplemented(); 384 } 385 386 #if ENABLE(OFFLINE_WEB_APPLICATIONS) reachedMaxAppCacheSize(int64_t spaceNeeded)387 void ChromeClientEfl::reachedMaxAppCacheSize(int64_t spaceNeeded) 388 { 389 // FIXME: Free some space. 390 notImplemented(); 391 } 392 reachedApplicationCacheOriginQuota(SecurityOrigin *)393 void ChromeClientEfl::reachedApplicationCacheOriginQuota(SecurityOrigin*) 394 { 395 notImplemented(); 396 } 397 #endif 398 399 #if ENABLE(TOUCH_EVENTS) needTouchEvents(bool needed)400 void ChromeClientEfl::needTouchEvents(bool needed) 401 { 402 ewk_view_need_touch_events_set(m_view, needed); 403 } 404 #endif 405 406 #if ENABLE(DATABASE) exceededDatabaseQuota(Frame * frame,const String & databaseName)407 void ChromeClientEfl::exceededDatabaseQuota(Frame* frame, const String& databaseName) 408 { 409 uint64_t quota; 410 SecurityOrigin* origin = frame->document()->securityOrigin(); 411 412 DatabaseDetails details = DatabaseTracker::tracker().detailsForNameAndOrigin(databaseName, origin); 413 quota = ewk_view_exceeded_database_quota(m_view, 414 kit(frame), databaseName.utf8().data(), 415 details.currentUsage(), details.expectedUsage()); 416 417 /* if client did not set quota, and database is being created now, the 418 * default quota is applied 419 */ 420 if (!quota && !DatabaseTracker::tracker().hasEntryForOrigin(origin)) 421 quota = ewk_settings_web_database_default_quota_get(); 422 423 DatabaseTracker::tracker().setQuota(origin, quota); 424 } 425 #endif 426 runOpenPanel(Frame * frame,PassRefPtr<FileChooser> prpFileChooser)427 void ChromeClientEfl::runOpenPanel(Frame* frame, PassRefPtr<FileChooser> prpFileChooser) 428 { 429 RefPtr<FileChooser> chooser = prpFileChooser; 430 bool confirm; 431 Eina_List* selectedFilenames = 0; 432 Eina_List* suggestedFilenames = 0; 433 void* filename; 434 Vector<String> filenames; 435 436 for (unsigned i = 0; i < chooser->filenames().size(); i++) { 437 CString str = chooser->filenames()[i].utf8(); 438 filename = strdup(str.data()); 439 suggestedFilenames = eina_list_append(suggestedFilenames, filename); 440 } 441 442 confirm = ewk_view_run_open_panel(m_view, kit(frame), chooser->allowsMultipleFiles(), suggestedFilenames, &selectedFilenames); 443 EINA_LIST_FREE(suggestedFilenames, filename) 444 free(filename); 445 446 if (!confirm) 447 return; 448 449 EINA_LIST_FREE(selectedFilenames, filename) { 450 filenames.append((char *)filename); 451 free(filename); 452 } 453 454 if (chooser->allowsMultipleFiles()) 455 chooser->chooseFiles(filenames); 456 else 457 chooser->chooseFile(filenames[0]); 458 } 459 formStateDidChange(const Node *)460 void ChromeClientEfl::formStateDidChange(const Node*) 461 { 462 notImplemented(); 463 } 464 setCursor(const Cursor &)465 void ChromeClientEfl::setCursor(const Cursor&) 466 { 467 notImplemented(); 468 } 469 requestGeolocationPermissionForFrame(Frame *,Geolocation *)470 void ChromeClientEfl::requestGeolocationPermissionForFrame(Frame*, Geolocation*) 471 { 472 // See the comment in WebCore/page/ChromeClient.h 473 notImplemented(); 474 } 475 cancelGeolocationPermissionRequestForFrame(Frame *,Geolocation *)476 void ChromeClientEfl::cancelGeolocationPermissionRequestForFrame(Frame*, Geolocation*) 477 { 478 notImplemented(); 479 } 480 cancelGeolocationPermissionForFrame(Frame *,Geolocation *)481 void ChromeClientEfl::cancelGeolocationPermissionForFrame(Frame*, Geolocation*) 482 { 483 notImplemented(); 484 } 485 invalidateContents(const IntRect & updateRect,bool immediate)486 void ChromeClientEfl::invalidateContents(const IntRect& updateRect, bool immediate) 487 { 488 notImplemented(); 489 } 490 invalidateWindow(const IntRect & updateRect,bool immediate)491 void ChromeClientEfl::invalidateWindow(const IntRect& updateRect, bool immediate) 492 { 493 notImplemented(); 494 } 495 invalidateContentsAndWindow(const IntRect & updateRect,bool immediate)496 void ChromeClientEfl::invalidateContentsAndWindow(const IntRect& updateRect, bool immediate) 497 { 498 Evas_Coord x, y, w, h; 499 500 x = updateRect.x(); 501 y = updateRect.y(); 502 w = updateRect.width(); 503 h = updateRect.height(); 504 ewk_view_repaint(m_view, x, y, w, h); 505 } 506 invalidateContentsForSlowScroll(const IntRect & updateRect,bool immediate)507 void ChromeClientEfl::invalidateContentsForSlowScroll(const IntRect& updateRect, bool immediate) 508 { 509 invalidateContentsAndWindow(updateRect, immediate); 510 } 511 scroll(const IntSize & scrollDelta,const IntRect & rectToScroll,const IntRect & clipRect)512 void ChromeClientEfl::scroll(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect) 513 { 514 ewk_view_scroll(m_view, scrollDelta.width(), scrollDelta.height(), rectToScroll.x(), rectToScroll.y(), rectToScroll.width(), rectToScroll.height(), clipRect.x(), clipRect.y(), clipRect.width(), clipRect.height(), EINA_TRUE); 515 } 516 cancelGeolocationPermissionRequestForFrame(Frame *)517 void ChromeClientEfl::cancelGeolocationPermissionRequestForFrame(Frame*) 518 { 519 notImplemented(); 520 } 521 iconForFiles(const Vector<String,0u> &,PassRefPtr<FileChooser>)522 void ChromeClientEfl::iconForFiles(const Vector<String, 0u>&, PassRefPtr<FileChooser>) 523 { 524 notImplemented(); 525 } 526 chooseIconForFiles(const Vector<String> &,FileChooser *)527 void ChromeClientEfl::chooseIconForFiles(const Vector<String>&, FileChooser*) 528 { 529 notImplemented(); 530 } 531 dispatchViewportDataDidChange(const ViewportArguments & arguments) const532 void ChromeClientEfl::dispatchViewportDataDidChange(const ViewportArguments& arguments) const 533 { 534 ewk_view_viewport_attributes_set(m_view, arguments); 535 } 536 selectItemWritingDirectionIsNatural()537 bool ChromeClientEfl::selectItemWritingDirectionIsNatural() 538 { 539 return true; 540 } 541 selectItemAlignmentFollowsMenuWritingDirection()542 bool ChromeClientEfl::selectItemAlignmentFollowsMenuWritingDirection() 543 { 544 return false; 545 } 546 createPopupMenu(PopupMenuClient * client) const547 PassRefPtr<PopupMenu> ChromeClientEfl::createPopupMenu(PopupMenuClient* client) const 548 { 549 return adoptRef(new PopupMenuEfl(client)); 550 } 551 createSearchPopupMenu(PopupMenuClient * client) const552 PassRefPtr<SearchPopupMenu> ChromeClientEfl::createSearchPopupMenu(PopupMenuClient* client) const 553 { 554 return adoptRef(new SearchPopupMenuEfl(client)); 555 } 556 557 } 558