Merge "[WK2] Change how to check the state of keypad" into 2.0_beta
[profile/ivi/webkit-efl.git] / Source / WebKit2 / WebProcess / WebPage / efl / WebPageEfl.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  * Portions Copyright (c) 2010 Motorola Mobility, Inc.  All rights reserved.
4  * Copyright (C) 2011 Igalia S.L.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
19  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25  * THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include "config.h"
29 #include "WebPage.h"
30
31 #include "NamedNodeMap.h"
32 #include "NotImplemented.h"
33 #include "WebEvent.h"
34 #include "WindowsKeyboardCodes.h"
35 #include <WebCore/EflKeyboardUtilities.h>
36 #include <WebCore/FocusController.h>
37 #include <WebCore/Frame.h>
38 #include <WebCore/KeyboardEvent.h>
39 #include <WebCore/Page.h>
40 #include <WebCore/PlatformKeyboardEvent.h>
41 #include <WebCore/Settings.h>
42
43 #if OS(TIZEN)
44 #include "Arguments.h"
45 #include "PlatformContextCairo.h"
46 #include "WebCoreArgumentCoders.h"
47 #include "WebFrame.h"
48 #include "WebImage.h"
49 #include "WebPageProxyMessages.h"
50 #include <WebCore/FrameView.h>
51
52 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION)
53 #include <WebCore/HTMLInputElement.h>
54 #include <WebCore/HTMLNames.h>
55 #endif
56
57 #if ENABLE(TIZEN_MOBILE_WEB_PRINT)
58 #include <WebCore/PlatformContextCairo.h>
59 #endif
60
61 #if ENABLE(TIZEN_SUPPORT_RSS_LINK_PARSING)
62 #include "HTMLLinkElement.h"
63 #include <WebCore/html/HTMLAllCollection.h>
64 #include <efl/RssItemEfl.h>
65 #endif
66
67 #if ENABLE(TIZEN_WEBKIT_PASTEBOARD)
68 #include <WebCore/Pasteboard.h>
69 #endif
70
71 #if ENABLE(TIZEN_WEBKIT2_REMOTE_WEB_INSPECTOR)
72 #include "WebInspectorServerEfl.h"
73 #endif
74
75 #if ENABLE(TIZEN_WEB_STORAGE)
76 #include <WebCore/GroupSettings.h>
77 #include <WebCore/PageGroup.h>
78 #endif
79
80 #if ENABLE(TIZEN_NPAPI)
81 #include "PluginView.h"
82 #endif
83
84 #if ENABLE(TIZEN_PREFERENCE)
85 #include "WebPreferencesStore.h"
86 #include <WebCore/Settings.h>
87 #endif
88
89 #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
90 #include <WebCore/HTMLFrameOwnerElement.h>
91 #include <WebCore/HTMLImageElement.h>
92 #endif
93
94 #if ENABLE(TIZEN_DEVICE_ORIENTATION)
95 #include "DeviceMotionClientEfl.h"
96 #include "DeviceOrientationClientEfl.h"
97 #endif
98
99 #if ENABLE(TIZEN_WEBKIT2_THEME_SET)
100 #include <WebCore/RenderThemeEfl.h>
101 #endif
102
103 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION_ON_UI_SIDE)
104 #include "RenderLayer.h"
105 #include "WebGraphicsLayer.h"
106 #endif
107
108 #if ENABLE(TIZEN_ISF_PORT)
109 #include "WebEditorClient.h"
110 #endif
111
112 #endif // #if OS(TIZEN)
113
114 using namespace WebCore;
115
116 namespace WebKit {
117
118 void WebPage::platformInitialize()
119 {
120 #if ENABLE(TIZEN_DEVICE_ORIENTATION)
121     WebCore::provideDeviceMotionTo(m_page.get(), new DeviceMotionClientEfl);
122     WebCore::provideDeviceOrientationTo(m_page.get(), new DeviceOrientationClientEfl);
123 #endif
124 }
125
126 #if ENABLE(TIZEN_PREFERENCE)
127 void WebPage::platformPreferencesDidChange(const WebPreferencesStore& store)
128 {
129     Settings* settings = m_page->settings();
130     settings->setInteractiveFormValidationEnabled(store.getBoolValueForKey(WebPreferencesKey::interactiveFormValidationEnabledKey()));
131     settings->setViewWidth(store.getUInt32ValueForKey(WebPreferencesKey::viewWidthKey()));
132     settings->setViewHeight(store.getUInt32ValueForKey(WebPreferencesKey::viewHeightKey()));
133     settings->setUsesEncodingDetector(store.getBoolValueForKey(WebPreferencesKey::usesEncodingDetectorKey()));
134 #if ENABLE(TIZEN_LOAD_REMOTE_IMAGES)
135     settings->setLoadRemoteImages(store.getBoolValueForKey(WebPreferencesKey::loadRemoteImagesKey()));
136 #endif
137 #if ENABLE(TIZEN_ISF_PORT)
138     settings->setShowImeOnAutofocus(store.getBoolValueForKey(WebPreferencesKey::showImeOnAutofocusKey()));
139     settings->setEnableDefaultKeypad(store.getBoolValueForKey(WebPreferencesKey::defaultKeypadEnabledKey()));
140 #endif
141 #if ENABLE(TIZEN_WAC_DISABLE_GEOLOCATION)
142     settings->setGeolocationEnabled(store.getBoolValueForKey(WebPreferencesKey::geolocationEnabledKey()));
143 #endif
144 }
145 #else
146 void WebPage::platformPreferencesDidChange(const WebPreferencesStore&)
147 {
148     notImplemented();
149 }
150 #endif // #if ENABLE(TIZEN_PREFERENCE)
151
152 static inline void scroll(Page* page, ScrollDirection direction, ScrollGranularity granularity)
153 {
154     page->focusController()->focusedOrMainFrame()->eventHandler()->scrollRecursively(direction, granularity);
155 }
156
157 bool WebPage::performDefaultBehaviorForKeyEvent(const WebKeyboardEvent& keyboardEvent)
158 {
159     notImplemented();
160     return false;
161 }
162
163 bool WebPage::platformHasLocalDataForURL(const KURL&)
164 {
165     notImplemented();
166     return false;
167 }
168
169 String WebPage::cachedResponseMIMETypeForURL(const KURL&)
170 {
171     notImplemented();
172     return String();
173 }
174
175 bool WebPage::platformCanHandleRequest(const ResourceRequest&)
176 {
177     notImplemented();
178     return true;
179 }
180
181 String WebPage::cachedSuggestedFilenameForURL(const KURL&)
182 {
183     notImplemented();
184     return String();
185 }
186
187 PassRefPtr<SharedBuffer> WebPage::cachedResponseDataForURL(const KURL&)
188 {
189     notImplemented();
190     return 0;
191 }
192
193 const char* WebPage::interpretKeyEvent(const KeyboardEvent* event)
194 {
195     ASSERT(event->type() == eventNames().keydownEvent || event->type() == eventNames().keypressEvent);
196
197     if (event->type() == eventNames().keydownEvent)
198         return getKeyDownCommandName(event);
199
200     return getKeyPressCommandName(event);
201 }
202
203 #if OS(TIZEN)
204
205 #if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
206 IntSize WebPage::contentsSize() const
207 {
208     FrameView* frameView = m_page->mainFrame()->view();
209     if (!frameView)
210         return IntSize(0, 0);
211
212     return frameView->contentsSize();
213 }
214 #endif
215
216 void WebPage::scrollMainFrameBy(const IntSize& scrollOffset)
217 {
218     m_page->mainFrame()->view()->scrollBy(scrollOffset);
219 }
220
221 void WebPage::scrollMainFrameTo(const IntPoint& scrollPosition)
222 {
223     m_page->mainFrame()->view()->setScrollPosition(scrollPosition);
224 }
225
226 void WebPage::createSnapshot(const IntRect rect, float scaleFactor, ShareableBitmap::Handle& snapshotHandle)
227 {
228     FrameView* frameView = m_mainFrame->coreFrame()->view();
229     if (!frameView)
230         return;
231
232     RefPtr<WebImage> snapshotImage = scaledSnapshotInViewCoordinates(rect, scaleFactor, ImageOptionsShareable);
233     if (!snapshotImage || !snapshotImage->bitmap())
234         return;
235
236     snapshotImage->bitmap()->createHandle(snapshotHandle);
237 }
238
239 void WebPage::requestUpdateFormNavigation()
240 {
241     Frame* frame = m_page->focusController()->focusedOrMainFrame();
242     if (!frame)
243         return;
244
245     Document* document = frame->document();
246     if (!document)
247         return;
248
249     Node* focusedNode = document->focusedNode();
250
251     Vector<RefPtr<Node> > focusableNodes;
252     document->getFocusableNodes(focusableNodes);
253
254     int formElementCount = 0;
255     int currentNodeIndex = -1;
256     const Vector<RefPtr<Node> >::iterator end = focusableNodes.end();
257     for (Vector<RefPtr<Node> >::iterator it = focusableNodes.begin(); it != end; ++it) {
258         AtomicString nodeName = (*it).get()->nodeName();
259         if (equalIgnoringCase(nodeName, "SELECT")
260             || (equalIgnoringCase(nodeName, "INPUT")
261                 && !equalIgnoringCase((*it).get()->toInputElement()->type(), "CHECKBOX")
262                 && !equalIgnoringCase((*it).get()->toInputElement()->type(), "RADIO")
263                 && !equalIgnoringCase((*it).get()->toInputElement()->type(), "SUBMIT")
264                 )
265             ) {
266             if ((*it).get() == focusedNode)
267                 currentNodeIndex = formElementCount;
268             formElementCount++;
269         }
270     }
271
272     if (currentNodeIndex == -1)
273         return;
274
275     send(Messages::WebPageProxy::UpdateFormNavigation(formElementCount, currentNodeIndex));
276 }
277
278 void WebPage::moveFocus(int newIndex)
279 {
280     Frame* frame = m_page->focusController()->focusedOrMainFrame();
281     if (!frame)
282         return;
283
284     Document* document = frame->document();
285     if (!document)
286         return;
287
288     Vector<RefPtr<Node> > focusableNodes;
289     document->getFocusableNodes(focusableNodes);
290
291     int index = 0;
292     const Vector<RefPtr<Node> >::iterator end = focusableNodes.end();
293     for (Vector<RefPtr<Node> >::iterator it = focusableNodes.begin(); it != end; ++it) {
294         AtomicString nodeName = (*it).get()->nodeName();
295         if (equalIgnoringCase(nodeName, "SELECT")) {
296             if (index == newIndex) {
297                 (*it).get()->setFocus();
298                 LayoutPoint position = LayoutPoint(0, 0);
299                 PlatformMouseEvent event(flooredIntPoint(position), flooredIntPoint(position), LeftButton, PlatformEvent::MouseMoved, 1, false, false, false, false, 0);
300                 (*it).get()->dispatchMouseEvent(event, "mousedown", 0, 0);
301             }
302             index++;
303         } else if (equalIgnoringCase(nodeName, "INPUT")
304             && !equalIgnoringCase((*it).get()->toInputElement()->type(), "CHECKBOX")
305             && !equalIgnoringCase((*it).get()->toInputElement()->type(), "RADIO")
306             ) {
307             if (index == newIndex) {
308                 HTMLInputElement* elem = (*it).get()->toInputElement();
309                 elem->focus();
310             }
311             index++;
312         }
313     }
314 }
315
316 #if ENABLE(TIZEN_MOBILE_WEB_PRINT)
317 #define A4_WIDTH 210
318 #define A4_HEIGHT 297
319 #define INCH_TO_MM 25.4
320 #define INCH_TO_POINTS 72.0
321
322 void WebPage::createPagesToPDF(const IntSize& size, const String& fileName)
323 {
324     FrameView* frameView = m_mainFrame->coreFrame()->view();
325     if (!frameView)
326         return;
327
328     RefPtr<WebImage> pageshotImage = WebImage::create(size, ImageOptionsShareable);
329     if (!pageshotImage->bitmap())
330         return;
331
332     double pdfWidth = A4_WIDTH / INCH_TO_MM * INCH_TO_POINTS;
333     double pdfHeight = A4_HEIGHT / INCH_TO_MM * INCH_TO_POINTS;
334     double scaleFactorPdf = pdfWidth / (double)size.width();
335
336     OwnPtr<WebCore::GraphicsContext> graphicsContext = pageshotImage->bitmap()->createGraphicsContextForPdfSurface(fileName, pdfWidth, pdfHeight);
337     graphicsContext->scale(FloatSize(scaleFactorPdf, scaleFactorPdf));
338
339     frameView->updateLayoutAndStyleIfNeededRecursive();
340
341     int pageNumber = ((size.height() * scaleFactorPdf) / pdfHeight) + 1;
342     IntRect paintRect(0, 0, size.width(), size.height());
343
344     PaintBehavior oldBehavior = frameView->paintBehavior();
345     frameView->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
346     for (int i = 0; i < pageNumber; i++) {
347         frameView->paint(graphicsContext.get(), paintRect);
348         cairo_show_page(graphicsContext->platformContext()->cr());
349         graphicsContext->translate(0, -ceil(pdfHeight / scaleFactorPdf));
350     }
351     frameView->setPaintBehavior(oldBehavior);
352
353     pageshotImage.release();
354 }
355 #endif
356
357 void WebPage::confirmComposition(const String& compositionString)
358 {
359     Frame* frame = m_page->focusController()->focusedOrMainFrame();
360     if (!frame || !frame->editor()->canEdit())
361         return;
362     frame->editor()->confirmComposition(compositionString);
363 }
364
365 void WebPage::setComposition(const String& compositionString, const Vector<WebCore::CompositionUnderline>& underlines, uint64_t cursorPosition)
366 {
367     Frame* frame = m_page->focusController()->focusedOrMainFrame();
368     if (!frame || !frame->editor()->canEdit())
369         return;
370     frame->editor()->setComposition(compositionString, underlines, cursorPosition, 0);
371 }
372
373 #if ENABLE(TIZEN_TEXT_CARET_HANDLING_WK2)
374 bool WebPage::setCaretPosition(const WebCore::IntPoint& pos)
375 {
376     Frame* frame = m_page->focusController()->focusedOrMainFrame();
377     if (!frame)
378         return false;
379
380     WebCore::FrameSelection* controller = frame->selection();
381     if (!controller)
382         return false;
383
384     FrameView* frameView = frame->view();
385     if (!frameView)
386         return false;
387
388     WebCore::IntPoint point = pos;
389     WebCore::HitTestResult result = frame->eventHandler()->hitTestResultAtPoint(frameView->windowToContents(point), /*allowShadowContent*/ true, /*ignoreClipping*/ true);
390     if (result.scrollbar())
391         return false;
392
393     WebCore::Node* innerNode = result.innerNode();
394
395     if (!innerNode || !innerNode->renderer())
396         return false;
397
398     WebCore::VisiblePosition visiblePos;
399
400     const int boundariesWidth = 2;
401
402     // we check if content is richly editable - because those input field behave other than plain text ones
403     // sometimes they may consists a node structure and they need special approach
404     if (innerNode->rendererIsRichlyEditable()) {
405         // point gets inner node local coordinates
406         point = flooredIntPoint(result.localPoint());
407         WebCore::IntRect rect = innerNode->renderer()->absoluteBoundingBoxRect(true);
408
409         // it is not the best way to do this, but it is not as slow and it works - so maybe in the future someone
410         // will have a better idea how to solve it
411         // here we are getting innerNode from HitTestResult - unfortunately this is a kind of high level node
412         // in the code below I am trying to obtain low level node - #text - to get its coordinates and size
413
414         // all those getting nodes rects are needed to bypass WebCore's methods of positioning caret when user
415         // is clicking outside a node - and cheat WebCore telling it that actually we clicked into input field
416         // node, not outside of it
417         WebCore::Node* deepInnerNode = innerNode->renderer()->positionForPoint(point).deepEquivalent().deprecatedNode();
418
419         if (!deepInnerNode || !deepInnerNode->renderer())
420             return false;
421
422         // so we get a base node rectange
423         WebCore::IntRect deepNodeRect = deepInnerNode->renderer()->absoluteBoundingBoxRect(true);
424
425         // we modify our local point to adjust it to base node local coordinates
426         point.move(rect.x() - deepNodeRect.x(), rect.y() - deepNodeRect.y());
427
428         // if we are outside the rect we cheat, that we are just inside of it
429         if (point.y() < 0)
430             point.setY(0);
431         else if (point.y() >= deepNodeRect.height())
432             point.setY(deepNodeRect.height() - 1);
433
434         // visible position created - caret ready to set
435         visiblePos = deepInnerNode->renderer()->positionForPoint(point);
436         if (visiblePos.isNull())
437             return false;
438     } else {
439         // for plain text input fields we can get only a caret bounding box
440         if (!controller->isCaret() || !controller->caretRenderer())
441             return false;
442
443         const WebCore::Node* node = controller->start().deprecatedNode();
444         if (!node || !node->renderer())
445             return false;
446
447         WebCore::IntRect rect = controller->caretRenderer()->absoluteBoundingBoxRect(true);
448
449         // here we also cheat input field that we actually are just inside of if
450         if (point.x() < rect.x())
451             point.setX(rect.x());
452         else if (point.x() > rect.maxX())
453             point.setX(rect.maxX());
454         if (point.y() < rect.y() + boundariesWidth)
455             point.setY(rect.y() + boundariesWidth);
456         else if (point.y() >= rect.maxY() - boundariesWidth)
457             point.setY(rect.maxY() - boundariesWidth - 1);
458
459         // hit test with fake (adjusted) coordinates
460         WebCore::HitTestResult newResult = frame->eventHandler()->hitTestResultAtPoint
461                 (point, /*allowShadowContent*/ true, /*ignoreClipping*/ true);
462
463         if (!newResult.isContentEditable())
464             return false;
465
466         WebCore::Node* newInnerNode = newResult.innerNode();
467
468         if (!newInnerNode || !newInnerNode->renderer())
469             return false;
470
471         // visible position created
472         visiblePos = newInnerNode->renderer()->positionForPoint(newResult.localPoint());
473         if (visiblePos.isNull())
474             return false;
475     }
476
477     // create visible selection from visible position
478     WebCore::VisibleSelection newSelection = WebCore::VisibleSelection(visiblePos);
479     controller->setSelection(newSelection, WebCore::CharacterGranularity);
480     // after setting selection caret blinking is suspended by default so we are unsuspedning it
481     controller->setCaretBlinkingSuspended(false);
482
483     return true;
484 }
485
486 void WebPage::getCaretPosition(WebCore::IntRect& rect)
487 {
488     Frame* frame = m_page->focusController()->focusedOrMainFrame();
489     if (!frame)
490         return;
491
492     WebCore::FrameSelection* controller = frame->selection();
493     if (!controller)
494         return;
495
496     WebCore::Node* node = controller->start().deprecatedNode();
497     if (!node || !node->renderer() || !node->isContentEditable())
498         return;
499
500     if (controller->isCaret()) {
501         FrameView* frameView = frame->view();
502         if (!frameView)
503             return;
504
505         rect = frameView->contentsToWindow(controller->absoluteCaretBounds());
506     }
507 }
508 #endif
509
510 #if ENABLE(TIZEN_ISF_PORT)
511 void WebPage::getCursorOffsetPosition(int& offset)
512 {
513     offset = 0;
514     Frame* frame = m_page->focusController()->focusedOrMainFrame();
515     if (!frame || !frame->editor()->canEdit())
516         return;
517
518     Position base = frame->selection()->base();
519     Node* baseNode = base.containerNode();
520     if (baseNode)
521         offset = baseNode->isTextNode() ? base.offsetInContainerNode() : 0;
522 }
523
524 void WebPage::getContentOfPosition(String& content)
525 {
526     Frame* frame = m_page->focusController()->focusedOrMainFrame();
527     if (!frame || !frame->editor()->canEdit())
528         return;
529
530     Position base = frame->selection()->base();
531     Node* baseNode = base.containerNode();
532     if (baseNode && baseNode->isTextNode())
533         content = baseNode->textContent();
534     else
535         content = String();
536 }
537
538 void WebPage::deleteSurroundingPosition(bool& result)
539 {
540     Frame* frame = m_page->focusController()->focusedOrMainFrame();
541     if (!frame || !frame->editor()->canEdit())
542         return;
543
544     frame->editor()->deleteWithDirection(DirectionBackward, CharacterGranularity, false, true);
545 }
546
547 void WebPage::handleInputMethodForFocusedNode()
548 {
549     Frame* frame = m_page->focusController()->focusedOrMainFrame();
550     if (frame
551         && frame->document()
552         && frame->document()->focusedNode())
553         corePage()->editorClient()->setInputMethodState(frame->document()->focusedNode()->shouldUseInputMethod());
554 }
555 #endif
556
557 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION)
558 void WebPage::setFocusedInputElementValue(const String& inputValue)
559 {
560     Frame* frame = m_page->focusController()->focusedOrMainFrame();
561     if (frame
562         && frame->document()
563         && frame->document()->focusedNode()) {
564         Node* node = frame->document()->focusedNode();
565         if (node->nodeType() == Node::ELEMENT_NODE) {
566             if (node->hasTagName(HTMLNames::inputTag)) {
567                 static_cast<HTMLInputElement*>(node)->setValue(inputValue, DispatchChangeEvent);
568                 static_cast<HTMLInputElement*>(node)->blur(); //  unfocus input element after set the value
569             }
570         }
571     }
572 }
573
574 void  WebPage::getFocusedInputElementValue(String& inputValue)
575 {
576     inputValue = String();
577
578     Frame* frame = m_page->focusController()->focusedOrMainFrame();
579     if (frame
580         && frame->document()
581         && frame->document()->focusedNode()) {
582         Node* node = frame->document()->focusedNode();
583         if (node->nodeType() == WebCore::Node::ELEMENT_NODE)
584             if (node->hasTagName(WebCore::HTMLNames::inputTag))
585                 inputValue = (static_cast<WebCore::HTMLInputElement*>(node))->value();
586     }
587 }
588 #endif
589
590 #if ENABLE(TIZEN_READER)
591 void WebPage::checkPageForReader(uint64_t callbackID)
592 {
593 }
594 #endif
595
596 #if ENABLE(TIZEN_WEBKIT2_HIT_TEST)
597 #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
598 static IntRect getFocusedRect(HitTestResult hitTestResult, Page* page)
599 {
600     IntRect focusedRect = IntRect(0, 0, 0, 0);
601     Node* node = hitTestResult.innerNode();
602     bool isFocusRingDrawable = false;
603     Node* focusableNode = node;
604     while (focusableNode) {
605         RenderObject* renderer = focusableNode->renderer();
606         if (renderer && renderer->isRoot())
607             break;
608
609         if (focusableNode->isFocusable()) {
610             if (focusableNode->isLink() || focusableNode->hasTagName(HTMLNames::inputTag))
611                 isFocusRingDrawable = true;
612             break;
613         }
614
615         focusableNode = focusableNode->parentNode();
616     }
617
618     if (!isFocusRingDrawable)
619         return focusedRect;
620
621     if (!hitTestResult.absoluteImageURL().isEmpty()) {
622         bool isReplaced;
623         IntRect imageNodeRect = pixelSnappedIntRect(node->getRect());
624         if (!focusableNode->renderRect(&isReplaced).isEmpty() && imageNodeRect.contains(pixelSnappedIntRect(focusableNode->getRect()))) {
625             // If render rect of focusableNode is empty and rect of imageNode include rect of focusableNode,
626             // we have to get rect of focusableNode.
627             // for example - The rect of google logo image in www.google.com pc site's search result page is bigger than rect of focusableNode.
628             // for example - The rect of category menu image in www.gmarket.co.kr pc site is bigger than rect of focusableNode.
629             focusedRect = pixelSnappedIntRect(focusableNode->getRect());
630         }
631         else {
632             // otherwise we have to get rect of imageNode.
633             // for example - The render rect of images in www.pudelek.pl is empty.
634             // for example - The rect of focusableNode of 'Test your browser GO' image in peacekeeper.futuremark.com is bigger than rect of 'Test your browser GO' image.
635             focusedRect = imageNodeRect;
636             focusableNode = node;
637         }
638     } else {
639         // If focusedNode have multiple child nodes, we have to unite rect of child nodes.
640         // for example - links in www.google.com's search result page.
641         IntRect tempRect = IntRect(0, 0, 0, 0);
642         for (Node* childNode = focusableNode->firstChild(); childNode; childNode = childNode->traverseNextNode(focusableNode)) {
643             bool isReplaced;
644             if (focusableNode->renderRect(&isReplaced).contains(childNode->getRect()))
645                 tempRect.unite(pixelSnappedIntRect(childNode->getRect()));
646         }
647
648         // If tempRect is empty or rect of focusableNode include tempRect,
649         // we have to get rect of focusableNode.
650         // for example - list menu item in m.naver.com.
651         // otherwise we have to get rect of tempRect.
652         if (tempRect.isEmpty() || focusableNode->getRect().contains(tempRect))
653             focusedRect = pixelSnappedIntRect(focusableNode->getRect());
654         else
655             focusedRect = tempRect;
656     }
657
658     // We have to get render rect from ancestor node if current focusedRect is empty.
659     // for example - The rect of naver logo image in www.naver.com pc site is empty.
660     bool isReplaced;
661     for (Node* loopNode = focusableNode; loopNode && focusedRect.isEmpty(); loopNode = loopNode->parentNode()) {
662         RenderObject* renderer = loopNode->renderer();
663         if (renderer && renderer->isRoot())
664             break;
665
666         focusedRect = pixelSnappedIntRect(loopNode->renderRect(&isReplaced));
667     }
668
669     Frame* mainFrame = page->mainFrame();
670     Frame* nodeFrame = focusableNode->document()->frame();
671     Node* owner;
672     while (nodeFrame && nodeFrame != mainFrame) {
673         owner = nodeFrame->ownerElement();
674         if (!owner)
675             break;
676
677         focusedRect.setX(focusedRect.x() + owner->getRect().x());
678         focusedRect.setY(focusedRect.y() + owner->getRect().y());
679         nodeFrame = owner->document()->frame();
680     }
681
682     // The y position of tab menu item in www.google.com is negative value,
683     // so we do not want to draw focus ring in that case.
684     if ((focusedRect.x() < 0) || (focusedRect.y() < 0))
685         focusedRect = IntRect(0, 0, 0, 0);
686
687     return focusedRect;
688 }
689 #endif
690
691 void WebPage::hitTestResultAtPoint(const IntPoint& point, int hitTestMode, WebHitTestResult::Data& hitTestResultData)
692 {
693     Frame* frame = m_page->focusController()->focusedOrMainFrame();
694     FrameView* frameView = frame->view();
695     if (!frameView)
696         return;
697
698     HitTestResult hitTestResult = frame->eventHandler()->hitTestResultAtPoint(frameView->windowToContents(point), false);
699     hitTestResultData.absoluteImageURL = hitTestResult.absoluteImageURL().string();
700     hitTestResultData.absoluteLinkURL = hitTestResult.absoluteLinkURL().string();
701     hitTestResultData.absoluteMediaURL = hitTestResult.absoluteMediaURL().string();
702     hitTestResultData.linkLabel = hitTestResult.textContent();
703     hitTestResultData.linkTitle = hitTestResult.titleDisplayString();
704
705     int context = WebHitTestResult::HitTestResultContextDocument;
706
707     if (!hitTestResult.absoluteLinkURL().isEmpty())
708         context |= WebHitTestResult::HitTestResultContextLink;
709     if (!hitTestResult.absoluteImageURL().isEmpty())
710         context |= WebHitTestResult::HitTestResultContextImage;
711     if (!hitTestResult.absoluteMediaURL().isEmpty())
712         context |= WebHitTestResult::HitTestResultContextMedia;
713     if (hitTestResult.isSelected())
714         context |= WebHitTestResult::HitTestResultContextSelection;
715     if (hitTestResult.isContentEditable())
716         context |= WebHitTestResult::HitTestResultContextEditable;
717     if (hitTestResult.innerNonSharedNode() && hitTestResult.innerNonSharedNode()->isTextNode())
718         context |= WebHitTestResult::HitTestResultContextText;
719
720     hitTestResultData.context = context;
721     hitTestResultData.hitTestMode = hitTestMode;
722
723 #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
724     hitTestResultData.focusedRect = getFocusedRect(hitTestResult, m_page.get());
725 #endif
726
727     if (hitTestResultData.hitTestMode & WebHitTestResult::HitTestModeNodeData) {
728         WebCore::Node* hitNode = hitTestResult.innerNonSharedNode();
729         if (hitNode) {
730             hitTestResultData.nodeData.nodeValue = hitNode->nodeValue();
731
732             if ((hitTestResultData.context & WebHitTestResult::HitTestResultContextText) && hitNode->parentNode())
733                 hitNode = hitNode->parentNode(); // if hittest inner node is Text node, fill tagName with parent node's info and fill attributeMap with parent node's attributes.
734
735             if (hitNode->isElementNode()) {
736                 WebCore::Element* hitElement = static_cast<WebCore::Element*>(hitNode);
737                 if (hitElement) {
738                     hitTestResultData.nodeData.tagName = hitElement->tagName();
739                 }
740             }
741
742             WebCore::NamedNodeMap* namedNodeMap = hitNode->attributes();
743             if (namedNodeMap) {
744                 for (size_t i = 0; i < namedNodeMap->length(); i++) {
745                     WebCore::Attribute* attribute = namedNodeMap->element()->attributeItem(i);
746                     String key = attribute->name().toString();
747                     String value = attribute->value();
748                     hitTestResultData.nodeData.attributeMap.add(key, value);
749                 }
750             }
751         }
752
753 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION_ON_UI_SIDE)
754         hitTestResultData.nodeData.isScrollableNodeFocused = false;
755         hitTestResultData.nodeData.enclosingWebLayerID = 0;
756         WebCore::RenderObject* renderer = hitTestResult.innerNode() ? hitTestResult.innerNode()->renderer() : 0;
757         while (renderer) {
758             if (renderer->isBoxModelObject() && renderer->hasLayer() && toRenderBoxModelObject(renderer)->layer()->hasAcceleratedTouchScrolling()) {
759                 hitTestResultData.nodeData.isScrollableNodeFocused = true;
760                 WebCore::GraphicsLayer* scrollingContentsLayer = renderer->enclosingLayer()->layerForScrollingContents();
761                 hitTestResultData.nodeData.enclosingWebLayerID = scrollingContentsLayer ? toWebGraphicsLayer(scrollingContentsLayer)->id() : 0;
762
763                 frame->eventHandler()->setMousePressNode(hitTestResult.innerNode());
764                 break;
765             }
766             renderer = renderer->parent();
767         }
768 #endif
769     }
770
771     if ((hitTestResultData.hitTestMode & WebHitTestResult::HitTestModeImageData) && (hitTestResultData.context & WebHitTestResult::HitTestResultContextImage)) {
772         WebCore::Image* hitImage = hitTestResult.image();
773         if (hitImage && hitImage->data() && hitImage->data()->data()) {
774             hitTestResultData.imageData.dataReference = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>(hitImage->data()->data()), hitImage->data()->size());
775             hitTestResultData.imageData.fileNameExtension = hitImage->filenameExtension();
776         }
777     }
778 }
779 #endif
780
781 #if ENABLE(TIZEN_SUPPORT_RSS_LINK_PARSING)
782 void WebPage::getRssItems(uint64_t callbackID)
783 {
784     if (!m_page->mainFrame())
785         return;
786     Document* document = m_page->mainFrame()->document();
787     if (!document)
788         return;
789     RefPtr<HTMLAllCollection>collection = document->all();
790
791     WTF::String Rss("application/rss+xml");
792     WTF::String Atom("application/atom+xml");
793     WTF::String Alternate("alternate");
794
795     Vector<RssItemEfl> rssItems;
796
797     for (Node* node = collection->firstItem(); node; node = collection->nextItem()) {
798         HTMLLinkElement* linkElement = static_cast<HTMLLinkElement*>(node);
799         if (linkElement->rel() == Alternate) {
800             RssItemEfl::LinkTypeEfl type;
801             if (linkElement->type() == Rss)
802                 type = RssItemEfl::LINK_TYPE_EFL_RSS;
803             else if (linkElement->type() == Atom)
804                 type = RssItemEfl::LINK_TYPE_EFL_ATOM;
805             else
806                 continue;
807
808             RssItemEfl rssItem(linkElement->href(), linkElement->title(), type);
809             rssItems.append(rssItem);
810         }
811     }
812     send(Messages::WebPageProxy::GetRssItemsCallback(rssItems, callbackID));
813
814     return;
815 }
816 #endif // #if ENABLE(TIZEN_SUPPORT_RSS_LINK_PARSING)
817
818 #if ENABLE(TIZEN_WEB_STORAGE)
819 void WebPage::getStorageQuotaBytes(uint64_t callbackID)
820 {
821     uint32_t quota = m_page->group().groupSettings()->localStorageQuotaBytes();
822     send(Messages::WebPageProxy::DidGetWebStorageQuotaBytes(quota, callbackID));
823 }
824
825 void WebPage::setStorageQuotaBytes(uint32_t quota)
826 {
827     m_page->group().groupSettings()->setLocalStorageQuotaBytes(quota);
828 }
829 #endif
830
831 #if ENABLE(TIZEN_WEBKIT2_THEME_SET)
832 void WebPage::setThemePath(const String& path)
833 {
834     Frame* mainFrame = m_page->mainFrame();
835     if (!mainFrame)
836         return;
837
838     WebCore::FrameView* view = mainFrame->view();
839     if (view) {
840         view->setEdjeTheme(path);
841         WebCore::RenderThemeEfl* theme = static_cast<RenderThemeEfl*>(m_page->theme());
842         theme->themeChanged();
843     }
844 }
845 #endif
846
847 #if ENABLE(TIZEN_RECORDING_SURFACE_SET)
848 void WebPage::recordingSurfaceSetEnableSet(bool enable)
849 {
850     m_recordingSurfaceSetSettings = enable;
851 }
852 #endif
853
854 #if ENABLE(TIZEN_WEBKIT_PASTEBOARD)
855 void WebPage::setDataToPasteboardWithType(const String& data, uint64_t type)
856 {
857     Pasteboard::generalPasteboard()->setDataWithType(data, static_cast<Pasteboard::PasteboardDataType>(type));
858 }
859 #endif
860
861 void WebPage::suspendJavaScriptAndResources()
862 {
863     Frame* mainFrame = m_page->mainFrame();
864     if (!mainFrame)
865         return;
866
867     for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext())
868         frame->document()->suspendScheduledTasks(WebCore::ActiveDOMObject::PageWillBeSuspended);
869     mainFrame->loader()->suspendAllLoaders();
870 }
871
872 void WebPage::resumeJavaScriptAndResources()
873 {
874     Frame* mainFrame = m_page->mainFrame();
875     if (!mainFrame)
876         return;
877
878     for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext())
879         frame->document()->resumeScheduledTasks();
880     mainFrame->loader()->resumeAllLoaders();
881 }
882
883 #if ENABLE(TIZEN_WEBKIT2_REMOTE_WEB_INSPECTOR)
884 void WebPage::startInspectorServer(uint32_t port,  uint32_t& allocatedPort)
885 {
886     bool ret = WebInspectorServerEfl::server()->startServer(port);
887     if (ret)
888         allocatedPort = WebInspectorServerEfl::server()->getServerPort();
889     else
890         allocatedPort = 0;
891 }
892
893 void WebPage::stopInspectorServer(bool& result)
894 {
895     result = WebInspectorServerEfl::server()->stopServer();
896 }
897 #endif
898
899 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION_ON_UI_SIDE)
900 void WebPage::scrollOverflowWithTrajectoryVector(const WebCore::FloatPoint& trajectoryVector)
901 {
902     Frame* frame = m_page->focusController()->focusedOrMainFrame();
903     if (!frame)
904         return;
905     frame->eventHandler()->scrollOverflow(trajectoryVector);
906 }
907 #endif
908
909 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL)
910 void WebPage::scrollOverflow(const WebCore::FloatPoint& delta, bool& scrolled)
911 {
912     scrolled = m_page->focusController()->focusedOrMainFrame()->eventHandler()->scrollOverflow(delta);
913 }
914
915 void WebPage::setPressedNodeAtPoint(const IntPoint& point, bool& pressed)
916 {
917     pressed = m_page->focusController()->focusedOrMainFrame()->eventHandler()->setMousePressNodeAtPoint(point);
918 }
919 #endif
920
921 void WebPage::executeEditCommandWithArgument(const String& commandName, const String& argument)
922 {
923     executeEditingCommand(commandName, argument);
924 }
925
926 #if ENABLE(TIZEN_FIX_PLUGIN_DOWNLOAD)
927 void WebPage::arePluginsEnabled(bool& enabled)
928 {
929     enabled = m_page->settings()->arePluginsEnabled();
930 }
931 #endif // ENABLE(TIZEN_FIX_PLUGIN_DOWNLOAD)
932
933 #if ENABLE(TIZEN_NPAPI)
934 void WebPage::suspendPlugin()
935 {
936     for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
937         FrameView* view = frame->view();
938         if (!view)
939             continue;
940
941         const HashSet<RefPtr<Widget> >* children = view->children();
942         ASSERT(children);
943
944         HashSet<RefPtr<Widget> >::const_iterator end = children->end();
945         for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) {
946             Widget* widget = (*it).get();
947             if (widget->isPluginViewBase()) {
948                 PluginView* pluginView = static_cast<PluginView*>(widget);
949                 if (pluginView)
950                     pluginView->suspendPlugin();
951             }
952         }
953     }
954 }
955
956 void WebPage::resumePlugin()
957 {
958     for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
959         FrameView* view = frame->view();
960         if (!view)
961             continue;
962
963         const HashSet<RefPtr<Widget> >* children = view->children();
964         ASSERT(children);
965
966         HashSet<RefPtr<Widget> >::const_iterator end = children->end();
967         for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) {
968             Widget* widget = (*it).get();
969             if (widget->isPluginViewBase()) {
970                 PluginView* pluginView = static_cast<PluginView*>(widget);
971                 if (pluginView)
972                     pluginView->resumePlugin();
973             }
974         }
975     }
976 }
977 #endif
978
979 #if ENABLE(TIZEN_WEBKIT2_GET_TEXT_STYLE_FOR_SELECTION)
980 void WebPage::getTextStyleStateForSelection()
981 {
982     Frame* frame = m_page->focusController()->focusedOrMainFrame();
983
984     int underlineState = frame->editor()->selectionHasStyle(CSSPropertyWebkitTextDecorationsInEffect, "underline");
985     int italicState = frame->editor()->selectionHasStyle(CSSPropertyFontStyle, "italic");
986     int boldState = frame->editor()->selectionHasStyle(CSSPropertyFontWeight, "bold");
987
988     send(Messages::WebPageProxy::DidGetTextStyleStateForSelection(underlineState, italicState, boldState));
989 }
990 #endif
991
992 #endif // #if OS(TIZEN)
993
994 } // namespace WebKit