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.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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.
31 #include "NamedNodeMap.h"
32 #include "NotImplemented.h"
34 #include "WindowsKeyboardCodes.h"
35 #include <WebCore/EflKeyboardUtilities.h>
36 #include <WebCore/FocusController.h>
37 #include <WebCore/Frame.h>
38 #include <WebCore/FrameView.h>
39 #include <WebCore/KeyboardEvent.h>
40 #include <WebCore/Page.h>
41 #include <WebCore/PlatformKeyboardEvent.h>
42 #include <WebCore/RenderThemeEfl.h>
43 #include <WebCore/Settings.h>
46 #include "Arguments.h"
47 #include "GraphicsContext.h"
48 #include "WebCoreArgumentCoders.h"
51 #include "WebPageProxyMessages.h"
52 #include <WebCore/FrameView.h>
54 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION)
55 #include <WebCore/HTMLInputElement.h>
56 #include <WebCore/HTMLNames.h>
59 #if ENABLE(TIZEN_MULTIPLE_SELECT)
60 #include "WebPopupMenu.h"
61 #include <WebCore/PopupMenuClient.h>
64 #if ENABLE(TIZEN_MOBILE_WEB_PRINT)
65 #include <WebCore/PlatformContextCairo.h>
68 #if ENABLE(TIZEN_CLIPBOARD) || ENABLE(TIZEN_PASTEBOARD)
69 #include <WebCore/ClipboardEfl.h>
72 #if ENABLE(TIZEN_PASTEBOARD)
73 #include <WebCore/Pasteboard.h>
76 #if ENABLE(TIZEN_WEBKIT2_REMOTE_WEB_INSPECTOR)
77 #include "WebInspectorServerEfl.h"
80 #if ENABLE(TIZEN_WEB_STORAGE)
81 #include <WebCore/GroupSettings.h>
82 #include <WebCore/PageGroup.h>
85 #if ENABLE(TIZEN_PLUGIN_SUSPEND_RESUME)
86 #include "PluginView.h"
89 #if ENABLE(TIZEN_PREFERENCE)
90 #include "WebPreferencesStore.h"
91 #include <WebCore/Settings.h>
94 #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
95 #include <WebCore/HTMLFrameOwnerElement.h>
96 #include <WebCore/HTMLImageElement.h>
99 #if ENABLE(TIZEN_DEVICE_ORIENTATION)
100 #include "DeviceMotionClientTizen.h"
101 #include "DeviceOrientationClientTizen.h"
104 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION_ON_UI_SIDE)
105 #include "RenderLayer.h"
106 #include "WebGraphicsLayer.h"
107 #include <WebCore/RenderView.h>
110 #if ENABLE(TIZEN_ISF_PORT)
111 #include "WebEditorClient.h"
112 #include <WebCore/Text.h>
115 #if ENABLE(TIZEN_DATALIST_ELEMENT)
116 #include "HTMLCollection.h"
117 #include "HTMLDataListElement.h"
118 #include "HTMLOptionElement.h"
121 #if ENABLE(TIZEN_STYLE_SCOPED)
122 #include <WebCore/RuntimeEnabledFeatures.h>
125 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
126 #include "htmlediting.h"
128 #endif // #if OS(TIZEN)
130 using namespace WebCore;
134 void WebPage::platformInitialize()
136 #if ENABLE(TIZEN_DEVICE_ORIENTATION)
137 WebCore::provideDeviceMotionTo(m_page.get(), new DeviceMotionClientTizen);
138 WebCore::provideDeviceOrientationTo(m_page.get(), new DeviceOrientationClientTizen);
142 #if ENABLE(TIZEN_PREFERENCE)
143 void WebPage::platformPreferencesDidChange(const WebPreferencesStore& store)
145 Settings* settings = m_page->settings();
146 settings->setInteractiveFormValidationEnabled(store.getBoolValueForKey(WebPreferencesKey::interactiveFormValidationEnabledKey()));
147 settings->setViewWidth(store.getUInt32ValueForKey(WebPreferencesKey::viewWidthKey()));
148 settings->setViewHeight(store.getUInt32ValueForKey(WebPreferencesKey::viewHeightKey()));
149 settings->setUsesEncodingDetector(store.getBoolValueForKey(WebPreferencesKey::usesEncodingDetectorKey()));
150 #if ENABLE(TIZEN_LOAD_REMOTE_IMAGES)
151 settings->setLoadRemoteImages(store.getBoolValueForKey(WebPreferencesKey::loadRemoteImagesKey()));
153 #if ENABLE(TIZEN_ISF_PORT)
154 settings->setEnableDefaultKeypad(store.getBoolValueForKey(WebPreferencesKey::defaultKeypadEnabledKey()));
156 #if ENABLE(TIZEN_STYLE_SCOPED)
157 WebCore::RuntimeEnabledFeatures::setStyleScopedEnabled(store.getBoolValueForKey(WebPreferencesKey::styleScopedEnabledKey()));
159 #if ENABLE(TIZEN_WEB_AUDIO)
160 settings->setWebAudioEnabled(true);
164 void WebPage::platformPreferencesDidChange(const WebPreferencesStore&)
168 #endif // #if ENABLE(TIZEN_PREFERENCE)
170 static inline void scroll(Page* page, ScrollDirection direction, ScrollGranularity granularity)
172 page->focusController()->focusedOrMainFrame()->eventHandler()->scrollRecursively(direction, granularity);
175 bool WebPage::performDefaultBehaviorForKeyEvent(const WebKeyboardEvent& keyboardEvent)
181 bool WebPage::platformHasLocalDataForURL(const KURL&)
187 String WebPage::cachedResponseMIMETypeForURL(const KURL&)
193 bool WebPage::platformCanHandleRequest(const ResourceRequest&)
199 String WebPage::cachedSuggestedFilenameForURL(const KURL&)
205 PassRefPtr<SharedBuffer> WebPage::cachedResponseDataForURL(const KURL&)
211 const char* WebPage::interpretKeyEvent(const KeyboardEvent* event)
213 ASSERT(event->type() == eventNames().keydownEvent || event->type() == eventNames().keypressEvent);
215 if (event->type() == eventNames().keydownEvent)
216 return getKeyDownCommandName(event);
218 return getKeyPressCommandName(event);
221 void WebPage::setThemePath(const String& themePath)
223 WebCore::RenderThemeEfl* theme = static_cast<WebCore::RenderThemeEfl*>(m_page->theme());
224 theme->setThemePath(themePath);
229 #if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
230 IntSize WebPage::contentsSize() const
232 FrameView* frameView = m_page->mainFrame()->view();
234 return IntSize(0, 0);
236 return frameView->contentsSize();
240 void WebPage::scrollMainFrameBy(const IntSize& scrollOffset)
242 m_page->mainFrame()->view()->scrollBy(scrollOffset);
245 void WebPage::scrollMainFrameTo(const IntPoint& scrollPosition)
247 m_page->mainFrame()->view()->setScrollPosition(scrollPosition);
250 void WebPage::createSnapshot(const IntRect rect, float scaleFactor, ShareableBitmap::Handle& snapshotHandle)
252 FrameView* frameView = m_mainFrame->coreFrame()->view();
256 RefPtr<WebImage> snapshotImage = scaledSnapshotInViewCoordinates(rect, scaleFactor, ImageOptionsShareable);
257 if (!snapshotImage || !snapshotImage->bitmap())
260 snapshotImage->bitmap()->createHandle(snapshotHandle);
263 void WebPage::requestUpdateFormNavigation()
265 Frame* frame = m_page->focusController()->focusedOrMainFrame();
269 Document* document = frame->document();
273 Node* focusedNode = document->focusedNode();
275 Vector<RefPtr<Node> > focusableNodes;
276 document->getFocusableNodes(focusableNodes);
278 int formElementCount = 0;
279 int currentNodeIndex = -1;
280 const Vector<RefPtr<Node> >::iterator end = focusableNodes.end();
281 for (Vector<RefPtr<Node> >::iterator it = focusableNodes.begin(); it != end; ++it) {
282 AtomicString nodeName = (*it).get()->nodeName();
283 if (equalIgnoringCase(nodeName, "SELECT")
284 || (equalIgnoringCase(nodeName, "INPUT")
285 && !equalIgnoringCase((*it).get()->toInputElement()->type(), "CHECKBOX")
286 && !equalIgnoringCase((*it).get()->toInputElement()->type(), "RADIO")
287 && !equalIgnoringCase((*it).get()->toInputElement()->type(), "SUBMIT")
290 if ((*it).get() == focusedNode)
291 currentNodeIndex = formElementCount;
296 if (currentNodeIndex == -1)
299 send(Messages::WebPageProxy::UpdateFormNavigation(formElementCount, currentNodeIndex));
302 void WebPage::moveFocus(int newIndex)
304 Frame* frame = m_page->focusController()->focusedOrMainFrame();
308 Document* document = frame->document();
312 Vector<RefPtr<Node> > focusableNodes;
313 document->getFocusableNodes(focusableNodes);
316 const Vector<RefPtr<Node> >::iterator end = focusableNodes.end();
317 for (Vector<RefPtr<Node> >::iterator it = focusableNodes.begin(); it != end; ++it) {
318 AtomicString nodeName = (*it).get()->nodeName();
319 if (equalIgnoringCase(nodeName, "SELECT")) {
320 if (index == newIndex) {
321 (*it).get()->setFocus();
322 LayoutPoint position = LayoutPoint(0, 0);
323 PlatformMouseEvent event(flooredIntPoint(position), flooredIntPoint(position), LeftButton, PlatformEvent::MouseMoved, 1, false, false, false, false, 0);
324 (*it).get()->dispatchMouseEvent(event, "mousedown", 0, 0);
327 } else if (equalIgnoringCase(nodeName, "INPUT")
328 && !equalIgnoringCase((*it).get()->toInputElement()->type(), "CHECKBOX")
329 && !equalIgnoringCase((*it).get()->toInputElement()->type(), "RADIO")
331 if (index == newIndex) {
332 HTMLInputElement* elem = (*it).get()->toInputElement();
340 #if ENABLE(TIZEN_MOBILE_WEB_PRINT)
341 #define INCH_TO_MM 25.4
342 #define INCH_TO_POINTS 72.0
344 void WebPage::createPagesToPDF(const IntSize& surfaceSize, const IntSize& contentsSize, const String& fileName)
346 FrameView* frameView = m_mainFrame->coreFrame()->view();
350 RefPtr<WebImage> pageshotImage = WebImage::create(contentsSize, ImageOptionsShareable);
351 if (!pageshotImage->bitmap())
354 double pdfWidth = (double)surfaceSize.width() / INCH_TO_MM * INCH_TO_POINTS;
355 double pdfHeight = (double)surfaceSize.height() / INCH_TO_MM * INCH_TO_POINTS;
356 double scaleFactorPdf = 1.0;
357 if (contentsSize.width() > pdfWidth)
358 scaleFactorPdf = pdfWidth / (double)contentsSize.width();
360 OwnPtr<WebCore::GraphicsContext> graphicsContext = pageshotImage->bitmap()->createGraphicsContextForPdfSurface(fileName, pdfWidth, pdfHeight);
361 graphicsContext->scale(FloatSize(scaleFactorPdf, scaleFactorPdf));
363 frameView->updateLayoutAndStyleIfNeededRecursive();
365 int pageNumber = ((contentsSize.height() * scaleFactorPdf) / pdfHeight) + 1;
368 PaintBehavior oldBehavior = frameView->paintBehavior();
369 frameView->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
370 for (int i = 0; i < pageNumber; i++) {
371 IntRect paintRect(0, (int)paintY, contentsSize.width(), (int)(pdfHeight / scaleFactorPdf));
373 frameView->paint(graphicsContext.get(), paintRect);
374 cairo_show_page(graphicsContext->platformContext()->cr());
375 graphicsContext->translate(0, -ceil(pdfHeight / scaleFactorPdf));
376 paintY += (pdfHeight / scaleFactorPdf);
378 frameView->setPaintBehavior(oldBehavior);
380 pageshotImage.release();
384 void WebPage::confirmComposition(const String& compositionString)
386 Frame* frame = m_page->focusController()->focusedOrMainFrame();
387 if (!frame || !frame->editor()->canEdit())
389 frame->editor()->confirmComposition(compositionString);
390 #if ENABLE(TIZEN_ISF_PORT)
391 send(Messages::WebPageProxy::UpdateCursorPosition());
395 void WebPage::setComposition(const String& compositionString, const Vector<WebCore::CompositionUnderline>& underlines, uint64_t cursorPosition)
397 Frame* frame = m_page->focusController()->focusedOrMainFrame();
398 if (!frame || !frame->editor()->canEdit())
400 #if ENABLE(TIZEN_ISF_PORT)
401 if (frame->selection()->rootEditableElement()) {
402 HTMLTextFormControlElement* textFormControl = toTextFormControl(frame->selection()->rootEditableElement()->shadowAncestorNode());
403 if (textFormControl && textFormControl->maxLength() >= 0) {
404 unsigned availableLength = textFormControl->maxLength() - textFormControl->value().length();
405 if (frame->editor()->hasComposition())
406 availableLength += (frame->editor()->compositionEnd() - frame->editor()->compositionStart());
407 if (!availableLength)
410 if (availableLength < compositionString.length()) {
411 String newCompositionString = compositionString.substring(0, availableLength);
412 Vector<CompositionUnderline> newUnderlines;
413 size_t numUnderlines = underlines.size();
414 for (size_t index = 0; index < numUnderlines; ++index) {
415 if (underlines[index].startOffset < availableLength) {
416 newUnderlines.append(underlines[index]);
417 if (newUnderlines.last().endOffset > availableLength)
418 newUnderlines.last().endOffset = availableLength;
421 frame->editor()->setComposition(newCompositionString, newUnderlines, cursorPosition, 0);
427 frame->editor()->setComposition(compositionString, underlines, cursorPosition, 0);
430 #if ENABLE(TIZEN_TEXT_CARET_HANDLING_WK2)
431 bool WebPage::setCaretPosition(const WebCore::IntPoint& pos)
433 Frame* frame = m_page->focusController()->focusedOrMainFrame();
437 WebCore::FrameSelection* controller = frame->selection();
441 FrameView* frameView = frame->view();
445 WebCore::IntPoint point = m_page->mainFrame()->view()->windowToContents(pos);
446 WebCore::HitTestResult result = m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(point, /*allowShadowContent*/ true, /*ignoreClipping*/ true);
447 if (result.scrollbar())
450 WebCore::Node* innerNode = result.innerNode();
452 if (!innerNode || !innerNode->renderer())
455 WebCore::VisiblePosition visiblePos;
457 const int boundariesWidth = 2;
459 // we check if content is richly editable - because those input field behave other than plain text ones
460 // sometimes they may consists a node structure and they need special approach
461 if (innerNode->rendererIsRichlyEditable()) {
462 // point gets inner node local coordinates
463 point = flooredIntPoint(result.localPoint());
464 WebCore::IntRect rect = innerNode->renderer()->absoluteBoundingBoxRect(true);
466 // it is not the best way to do this, but it is not as slow and it works - so maybe in the future someone
467 // will have a better idea how to solve it
468 // here we are getting innerNode from HitTestResult - unfortunately this is a kind of high level node
469 // in the code below I am trying to obtain low level node - #text - to get its coordinates and size
471 // all those getting nodes rects are needed to bypass WebCore's methods of positioning caret when user
472 // is clicking outside a node - and cheat WebCore telling it that actually we clicked into input field
473 // node, not outside of it
474 WebCore::Node* deepInnerNode = innerNode->renderer()->positionForPoint(point).deepEquivalent().deprecatedNode();
476 if (!deepInnerNode || !deepInnerNode->renderer())
479 // so we get a base node rectange
480 WebCore::IntRect deepNodeRect = deepInnerNode->renderer()->absoluteBoundingBoxRect(true);
482 // we modify our local point to adjust it to base node local coordinates
483 point.move(rect.x() - deepNodeRect.x(), rect.y() - deepNodeRect.y());
485 // if we are outside the rect we cheat, that we are just inside of it
488 else if (point.y() >= deepNodeRect.height())
489 point.setY(deepNodeRect.height() - 1);
491 // visible position created - caret ready to set
492 visiblePos = deepInnerNode->renderer()->positionForPoint(point);
493 if (visiblePos.isNull())
496 // for plain text input fields we can get only a caret bounding box
497 if (!controller->isCaret() || !controller->caretRenderer())
500 const WebCore::Node* node = controller->start().deprecatedNode();
501 if (!node || !node->renderer())
504 WebCore::IntRect rect = controller->caretRenderer()->absoluteBoundingBoxRect(true);
506 // FIXME: The below codes should be updated to apply the positon of focusedFrame.
508 // here we also cheat input field that we actually are just inside of if
509 if (point.x() < rect.x())
510 point.setX(rect.x());
511 else if (point.x() > rect.maxX())
512 point.setX(rect.maxX());
513 if (point.y() < rect.y() + boundariesWidth)
514 point.setY(rect.y() + boundariesWidth);
515 else if (point.y() >= rect.maxY() - boundariesWidth)
516 point.setY(rect.maxY() - boundariesWidth - 1);
519 // hit test with fake (adjusted) coordinates
520 WebCore::IntPoint hitTestPoint = m_page->mainFrame()->view()->windowToContents(point);
521 WebCore::HitTestResult newResult = m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(hitTestPoint, /*allowShadowContent*/ true, /*ignoreClipping*/ true);
523 if (!newResult.isContentEditable())
526 WebCore::Node* newInnerNode = newResult.innerNode();
528 if (!newInnerNode || !newInnerNode->renderer())
531 // visible position created
532 visiblePos = newInnerNode->renderer()->positionForPoint(newResult.localPoint());
533 if (visiblePos.isNull())
537 // create visible selection from visible position
538 WebCore::VisibleSelection newSelection = WebCore::VisibleSelection(visiblePos);
539 controller->setSelection(newSelection, WebCore::CharacterGranularity);
540 // after setting selection caret blinking is suspended by default so we are unsuspedning it
541 controller->setCaretBlinkingSuspended(false);
546 void WebPage::getCaretPosition(WebCore::IntRect& rect)
548 Frame* frame = m_page->focusController()->focusedOrMainFrame();
552 WebCore::FrameSelection* controller = frame->selection();
556 WebCore::Node* node = controller->start().deprecatedNode();
557 if (!node || !node->renderer() || !node->isContentEditable())
560 if (controller->isCaret()) {
561 FrameView* frameView = frame->view();
565 rect = frameView->contentsToWindow(controller->absoluteCaretBounds());
570 #if ENABLE(TIZEN_ISF_PORT)
571 void WebPage::getCursorOffsetPosition(int& offset)
574 Frame* frame = m_page->focusController()->focusedOrMainFrame();
575 if (!frame || !frame->editor()->canEdit())
578 Position base = frame->selection()->base();
579 Node* baseNode = base.containerNode();
581 offset = baseNode->isTextNode() ? base.offsetInContainerNode() : 0;
584 void WebPage::getContentOfPosition(String& content)
586 Frame* frame = m_page->focusController()->focusedOrMainFrame();
587 if (!frame || !frame->editor()->canEdit())
590 Position base = frame->selection()->base();
591 Node* baseNode = base.containerNode();
592 if (baseNode && baseNode->isTextNode())
593 content = baseNode->textContent();
598 void WebPage::deleteSurroundingPosition(bool& result)
600 Frame* frame = m_page->focusController()->focusedOrMainFrame();
601 if (!frame || !frame->editor()->canEdit())
604 frame->editor()->deleteWithDirection(DirectionBackward, CharacterGranularity, false, true);
607 void WebPage::getSelectionRect(bool isOnlyEditable, IntRect& rect)
611 Frame* frame = m_page->focusController()->focusedFrame();
612 if (!frame || !frame->view())
615 FrameSelection* selection = frame->selection();
616 Node* node = selection->start().deprecatedNode();
617 if (!node || !node->renderer() || (isOnlyEditable && !node->isContentEditable()))
620 if (selection->isCaret())
621 rect = frame->view()->contentsToWindow(selection->absoluteCaretBounds());
622 else if (selection->isRange())
623 rect = frame->view()->contentsToWindow(enclosingIntRect(selection->bounds()));
627 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION)
628 void WebPage::setFocusedInputElementValue(const String& inputValue)
630 Frame* frame = m_page->focusController()->focusedOrMainFrame();
631 if (!frame || !frame->document() || !frame->document()->focusedNode())
634 HTMLInputElement* inputElement = frame->document()->focusedNode()->toInputElement();
638 inputElement->toNode()->dispatchFocusEvent(0);
639 inputElement->setValue(inputValue, DispatchChangeEvent);
642 void WebPage::getFocusedInputElementValue(String& inputValue)
644 inputValue = String();
646 Frame* frame = m_page->focusController()->focusedOrMainFrame();
647 if (!frame || !frame->document() || !frame->document()->focusedNode())
650 HTMLInputElement* inputElement = frame->document()->focusedNode()->toInputElement();
654 inputValue = inputElement->value();
658 #if ENABLE(TIZEN_DATALIST_ELEMENT)
659 void WebPage::getFocusedInputElementDataList(Vector<String>& optionList)
661 Frame* frame = m_page->focusController()->focusedOrMainFrame();
662 if (!frame || !frame->document())
665 Node* node = frame->document()->focusedNode();
669 HTMLInputElement* input = node->toInputElement();
673 HTMLDataListElement* dataList = static_cast<HTMLDataListElement*>(input->list());
677 RefPtr<HTMLCollection> options = static_cast<HTMLDataListElement*>(dataList)->options();
678 for (unsigned i = 0; Node* node = options->item(i); i++) {
679 HTMLOptionElement* optionElement = static_cast<HTMLOptionElement*>(node);
680 String value = optionElement->value();
681 optionList.append(value);
686 #if ENABLE(TIZEN_WEBKIT2_HIT_TEST)
687 #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
688 static IntRect getFocusedRect(HitTestResult hitTestResult, Page* page)
690 IntRect focusedRect = IntRect(0, 0, 0, 0);
691 Node* node = hitTestResult.innerNode();
692 bool isFocusRingDrawable = false;
693 Node* focusableNode = node;
694 while (focusableNode) {
695 RenderObject* renderer = focusableNode->renderer();
696 if (renderer && renderer->isRoot())
699 if (focusableNode->isFocusable()) {
700 if (focusableNode->isLink()
701 || focusableNode->hasTagName(HTMLNames::inputTag)
702 || focusableNode->hasTagName(HTMLNames::selectTag)
703 || focusableNode->hasTagName(HTMLNames::buttonTag))
704 isFocusRingDrawable = true;
708 focusableNode = focusableNode->parentNode();
711 if (!isFocusRingDrawable)
714 if (!hitTestResult.absoluteImageURL().isEmpty()) {
716 IntRect imageNodeRect = pixelSnappedIntRect(node->getRect());
717 if (!focusableNode->renderRect(&isReplaced).isEmpty() && imageNodeRect.contains(pixelSnappedIntRect(focusableNode->getRect()))) {
718 // If render rect of focusableNode is empty and rect of imageNode include rect of focusableNode,
719 // we have to get rect of focusableNode.
720 // for example - The rect of google logo image in www.google.com pc site's search result page is bigger than rect of focusableNode.
721 // for example - The rect of category menu image in www.gmarket.co.kr pc site is bigger than rect of focusableNode.
722 focusedRect = pixelSnappedIntRect(focusableNode->getRect());
725 // otherwise we have to get rect of imageNode.
726 // for example - The render rect of images in www.pudelek.pl is empty.
727 // 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.
728 focusedRect = imageNodeRect;
729 focusableNode = node;
732 // If focusedNode have multiple child nodes, we have to unite rect of child nodes.
733 // for example - links in www.google.com's search result page.
734 IntRect tempRect = IntRect(0, 0, 0, 0);
735 for (Node* childNode = focusableNode->firstChild(); childNode; childNode = childNode->traverseNextNode(focusableNode)) {
737 if (focusableNode->renderRect(&isReplaced).contains(childNode->getRect()))
738 tempRect.unite(pixelSnappedIntRect(childNode->getRect()));
741 // If tempRect is empty or rect of focusableNode include tempRect,
742 // we have to get rect of focusableNode.
743 // for example - list menu item in m.naver.com.
744 // otherwise we have to get rect of tempRect.
745 // getRect API do not return correct rect if the node is a container node,
746 // hence using absoluteBoundingBoxRect to get the correct bounding rect.
747 LayoutRect renderRect = focusableNode->renderer() ? focusableNode->renderer()->absoluteBoundingBoxRect() : focusableNode->getRect();
748 if (tempRect.isEmpty() || renderRect.contains(tempRect))
749 focusedRect = pixelSnappedIntRect(renderRect);
751 focusedRect = tempRect;
754 // We have to get render rect from ancestor node if current focusedRect is empty.
755 // for example - The rect of naver logo image in www.naver.com pc site is empty.
757 for (Node* loopNode = focusableNode; loopNode && focusedRect.isEmpty(); loopNode = loopNode->parentNode()) {
758 RenderObject* renderer = loopNode->renderer();
759 if (renderer && renderer->isRoot())
762 focusedRect = pixelSnappedIntRect(loopNode->renderRect(&isReplaced));
765 Frame* mainFrame = page->mainFrame();
766 Frame* nodeFrame = focusableNode->document()->frame();
768 while (nodeFrame && nodeFrame != mainFrame) {
769 owner = nodeFrame->ownerElement();
773 focusedRect.setX(focusedRect.x() + owner->getRect().x());
774 focusedRect.setY(focusedRect.y() + owner->getRect().y());
775 nodeFrame = owner->document()->frame();
778 // The y position of tab menu item in www.google.com is negative value,
779 // so we do not want to draw focus ring in that case.
780 if ((focusedRect.x() < 0) || (focusedRect.y() < 0))
781 focusedRect = IntRect(0, 0, 0, 0);
787 void WebPage::hitTestResultAtPoint(const IntPoint& point, int hitTestMode, WebHitTestResult::Data& hitTestResultData)
789 Frame* frame = m_page->mainFrame();
790 FrameView* frameView = frame->view();
794 HitTestResult hitTestResult = frame->eventHandler()->hitTestResultAtPoint(frameView->windowToContents(point), false);
795 hitTestResultData.absoluteImageURL = hitTestResult.absoluteImageURL().string();
796 hitTestResultData.absoluteLinkURL = hitTestResult.absoluteLinkURL().string();
797 hitTestResultData.absoluteMediaURL = hitTestResult.absoluteMediaURL().string();
798 hitTestResultData.linkLabel = hitTestResult.textContent();
799 hitTestResultData.linkTitle = hitTestResult.titleDisplayString();
800 #if ENABLE(TIZEN_DRAG_SUPPORT)
801 hitTestResultData.isDragSupport = hitTestResult.isDragSupport();
804 int context = WebHitTestResult::HitTestResultContextDocument;
806 if (!hitTestResult.absoluteLinkURL().isEmpty())
807 context |= WebHitTestResult::HitTestResultContextLink;
808 if (!hitTestResult.absoluteImageURL().isEmpty())
809 context |= WebHitTestResult::HitTestResultContextImage;
810 if (!hitTestResult.absoluteMediaURL().isEmpty())
811 context |= WebHitTestResult::HitTestResultContextMedia;
812 if (hitTestResult.isSelected())
813 context |= WebHitTestResult::HitTestResultContextSelection;
814 if (hitTestResult.isContentEditable())
815 context |= WebHitTestResult::HitTestResultContextEditable;
816 if (hitTestResult.innerNonSharedNode() && hitTestResult.innerNonSharedNode()->isTextNode())
817 context |= WebHitTestResult::HitTestResultContextText;
819 hitTestResultData.context = context;
820 hitTestResultData.hitTestMode = hitTestMode;
822 #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
823 hitTestResultData.focusedRect = getFocusedRect(hitTestResult, m_page.get());
824 if (hitTestResult.innerNode() && hitTestResult.innerNode()->renderer() && hitTestResult.innerNode()->renderer()->style()) {
825 hitTestResultData.focusedColor = hitTestResult.innerNode()->renderer()->style()->tapHighlightColor();
826 if (!hitTestResultData.focusedColor.hasAlpha())
827 hitTestResultData.focusedColor = Color(hitTestResultData.focusedColor.red(), hitTestResultData.focusedColor.green(), hitTestResultData.focusedColor.blue(), RenderStyle::initialTapHighlightColor().alpha());
831 if (hitTestResultData.hitTestMode & WebHitTestResult::HitTestModeNodeData) {
832 WebCore::Node* hitNode = hitTestResult.innerNonSharedNode();
834 hitTestResultData.nodeData.nodeValue = hitNode->nodeValue();
836 if ((hitTestResultData.context & WebHitTestResult::HitTestResultContextText) && hitNode->parentNode())
837 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.
839 if (hitNode->isElementNode()) {
840 WebCore::Element* hitElement = static_cast<WebCore::Element*>(hitNode);
842 hitTestResultData.nodeData.tagName = hitElement->tagName();
846 WebCore::NamedNodeMap* namedNodeMap = hitNode->attributes();
848 for (size_t i = 0; i < namedNodeMap->length(); i++) {
849 const WebCore::Attribute* attribute = namedNodeMap->element()->attributeItem(i);
850 String key = attribute->name().toString();
851 String value = attribute->value();
852 hitTestResultData.nodeData.attributeMap.add(key, value);
858 if ((hitTestResultData.hitTestMode & WebHitTestResult::HitTestModeImageData) && (hitTestResultData.context & WebHitTestResult::HitTestResultContextImage)) {
859 WebCore::Image* hitImage = hitTestResult.image();
860 if (hitImage && hitImage->data() && hitImage->data()->data()) {
861 hitTestResultData.imageData.data.append(hitImage->data()->data(), hitImage->data()->size());
862 hitTestResultData.imageData.fileNameExtension = hitImage->filenameExtension();
868 #if ENABLE(TIZEN_WEB_STORAGE)
869 void WebPage::getStorageQuotaBytes(uint64_t callbackID)
871 uint32_t quota = m_page->group().groupSettings()->localStorageQuotaBytes();
872 send(Messages::WebPageProxy::DidGetWebStorageQuotaBytes(quota, callbackID));
875 void WebPage::setStorageQuotaBytes(uint32_t quota)
877 m_page->group().groupSettings()->setLocalStorageQuotaBytes(quota);
881 #if ENABLE(TIZEN_RECORDING_SURFACE_SET)
882 void WebPage::recordingSurfaceSetEnableSet(bool enable)
884 m_recordingSurfaceSetSettings = enable;
888 #if ENABLE(TIZEN_CLIPBOARD) || ENABLE(TIZEN_PASTEBOARD)
889 void WebPage::setClipboardDataForPaste(const String& data, const String& type)
891 #if ENABLE(TIZEN_PASTEBOARD)
892 // FIXME: Should move to EditorClient like Clipboard
893 Pasteboard::generalPasteboard()->setDataWithType(data, type);
895 Frame* mainFrame = m_page->mainFrame();
899 mainFrame->editor()->client()->setClipboardDataForPaste(data, type);
904 void WebPage::suspendJavaScriptAndResources()
906 Frame* mainFrame = m_page->mainFrame();
910 for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext())
911 frame->document()->suspendScheduledTasks(WebCore::ActiveDOMObject::PageWillBeSuspended);
912 mainFrame->loader()->suspendAllLoaders();
915 void WebPage::resumeJavaScriptAndResources()
917 Frame* mainFrame = m_page->mainFrame();
921 for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext())
922 frame->document()->resumeScheduledTasks();
923 mainFrame->loader()->resumeAllLoaders();
926 #if ENABLE(TIZEN_SYNC_REQUEST_ANIMATION_FRAME)
927 void WebPage::suspendAnimationController()
929 if (!m_suspendedAnimationController) {
930 Frame* mainFrame = m_page->mainFrame();
934 for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext())
935 frame->document()->suspendScriptedAnimationControllerCallbacks();
937 m_suspendedAnimationController = true;
941 void WebPage::resumeAnimationController()
943 if (m_suspendedAnimationController) {
944 Frame* mainFrame = m_page->mainFrame();
948 for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext())
949 frame->document()->resumeScriptedAnimationControllerCallbacks();
951 m_suspendedAnimationController = false;
956 #if ENABLE(TIZEN_WEBKIT2_REMOTE_WEB_INSPECTOR)
957 void WebPage::startInspectorServer(uint32_t port, uint32_t& allocatedPort)
959 bool ret = WebInspectorServerEfl::server()->startServer(port);
961 allocatedPort = WebInspectorServerEfl::server()->getServerPort();
966 void WebPage::stopInspectorServer(bool& result)
968 result = WebInspectorServerEfl::server()->stopServer();
972 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION_ON_UI_SIDE)
973 void WebPage::scrollOverflowWithTrajectoryVector(const WebCore::FloatPoint& trajectoryVector)
975 Frame* frame = m_page->focusController()->focusedOrMainFrame();
978 frame->eventHandler()->scrollOverflow(trajectoryVector);
982 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
983 void WebPage::scrollOverflow(const WebCore::FloatPoint& delta, bool& scrolled)
985 scrolled = m_page->focusController()->focusedOrMainFrame()->eventHandler()->scrollOverflow(delta);
988 void WebPage::setPressedNodeAtPoint(const IntPoint& point, bool checkOverflowLayer, bool& pressed, uint32_t& id)
990 RenderObject* renderer = 0;
992 pressed = m_page->focusController()->focusedOrMainFrame()->eventHandler()->setMousePressNodeAtPoint(point, checkOverflowLayer, renderer);
993 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION_ON_UI_SIDE)
994 if (pressed && renderer)
995 id = toWebGraphicsLayer(renderer->enclosingLayer()->layerForScrollingContents())->id();
1000 void WebPage::executeEditCommandWithArgument(const String& commandName, const String& argument)
1002 executeEditingCommand(commandName, argument);
1005 #if ENABLE(TIZEN_PLUGIN_SUSPEND_RESUME)
1006 void WebPage::suspendPlugin()
1008 for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
1009 FrameView* view = frame->view();
1013 const HashSet<RefPtr<Widget> >* children = view->children();
1016 HashSet<RefPtr<Widget> >::const_iterator end = children->end();
1017 for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) {
1018 Widget* widget = (*it).get();
1019 if (widget->isPluginViewBase()) {
1020 PluginView* pluginView = static_cast<PluginView*>(widget);
1022 pluginView->suspendPlugin();
1028 void WebPage::resumePlugin()
1030 for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
1031 FrameView* view = frame->view();
1035 const HashSet<RefPtr<Widget> >* children = view->children();
1038 HashSet<RefPtr<Widget> >::const_iterator end = children->end();
1039 for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) {
1040 Widget* widget = (*it).get();
1041 if (widget->isPluginViewBase()) {
1042 PluginView* pluginView = static_cast<PluginView*>(widget);
1044 pluginView->resumePlugin();
1051 #if ENABLE(TIZEN_WEBKIT2_GET_TEXT_STYLE_FOR_SELECTION)
1052 void WebPage::getTextStyleStateForSelection()
1054 Frame* frame = m_page->focusController()->focusedOrMainFrame();
1056 int underlineState = frame->editor()->selectionHasStyle(CSSPropertyWebkitTextDecorationsInEffect, "underline");
1057 int italicState = frame->editor()->selectionHasStyle(CSSPropertyFontStyle, "italic");
1058 int boldState = frame->editor()->selectionHasStyle(CSSPropertyFontWeight, "bold");
1060 send(Messages::WebPageProxy::DidGetTextStyleStateForSelection(underlineState, italicState, boldState));
1064 #if ENABLE(TIZEN_MULTIPLE_SELECT)
1065 void WebPage::didChangeSelectedIndexForActivePopupMenuMultiple(Vector<int32_t> newIndex)
1067 if (!m_activePopupMenu)
1070 m_activePopupMenu->client()->popupDidHide();
1072 size_t indexSize = newIndex.size();
1073 for (size_t i = 0; i < indexSize; i++)
1074 m_activePopupMenu->didChangeSelectedIndex(i);
1077 m_activePopupMenu = 0;
1082 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
1083 void WebPage::selectClosestWord(const WebCore::IntPoint& point, bool isStartedTextSelectionFromOutside, bool& result)
1087 Frame* mainFrame = m_page->mainFrame();
1088 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1090 HitTestResult hitTestResult = mainFrame->eventHandler()->hitTestResultAtPoint(m_page->mainFrame()->view()->windowToContents(point), false);
1092 if (hitTestResult.isContentEditable()) {
1093 result = setCaretPosition(point);
1097 if (hitTestResult.innerNonSharedNode() && hitTestResult.innerNonSharedNode()->isTextNode()) {
1098 if (!isStartedTextSelectionFromOutside) {
1099 for (Node* node = hitTestResult.innerNonSharedNode(); node; node = node->parentNode()) {
1100 if (node->isFocusable()) {
1101 // Text selection shoud not be started when text of <button> tag is selected.
1102 if (node->hasTagName(HTMLNames::buttonTag))
1109 WebCore::FrameSelection* frameSelection = focusedFrame->selection();
1111 WebCore::VisiblePosition position = mainFrame->visiblePositionForPoint(point);
1112 WebCore::VisibleSelection selection(position);
1114 // This changes just the 'start' and 'end' positions of the VisibleSelection
1115 selection.expandUsingGranularity(WebCore::WordGranularity);
1117 frameSelection->setSelection(WebCore::VisibleSelection(selection.start(), selection.end()));
1119 if (!frameSelection->isRange())
1122 // This changes just the 'start' and 'end' positions of the VisibleSelection
1123 // Find handlers positions
1124 WebCore::IntRect leftRect, rightRect;
1125 getSelectionHandlers(leftRect, rightRect);
1126 if (leftRect.size().isZero() && rightRect.size().isZero()) {
1127 // Sometimes there is no selected text, but isNone() returns TRUE
1128 // in this case ewk_frame_selection_handlers_get() returns FALSE and handlers are invalid
1129 // Workaround - clear the selection.
1130 // Better solution would be to modify the ewk_frame_select_closest_word()
1131 // to not select anything in the first place (for example - don't call setSelection()
1132 // if there is nothing under the cursor).
1133 frameSelection->clear();
1141 void WebPage::setLeftSelection(const WebCore::IntPoint& point, bool& result)
1145 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1146 WebCore::FrameSelection* frameSelection = focusedFrame->selection();
1147 if (!frameSelection->isRange())
1150 WebCore::Node* selectionEndNode = frameSelection->end().deprecatedNode();
1151 if (!selectionEndNode || !selectionEndNode->renderer())
1154 FrameView* frameView = focusedFrame->view();
1158 WebCore::IntPoint pos = frameView->windowToContents(point);
1159 WebCore::IntRect leftRect, rightRect;
1160 getSelectionHandlers(leftRect, rightRect);
1161 if ((rightRect.y() + rightRect.height()) < pos.y())
1162 pos.setY(rightRect.y() + (rightRect.height()/2));
1164 if (selectionEndNode->rendererIsEditable() && !selectionEndNode->rendererIsRichlyEditable()) {
1165 const int boundariesWidth = 2;
1167 WebCore::IntRect rect = frameSelection->caretRenderer()->absoluteBoundingBoxRect(true);
1168 // here we cheat input field that we actually are just inside of if
1169 if (pos.y() < rect.y() + boundariesWidth)
1170 pos.setY(rect.y() + boundariesWidth);
1171 else if (pos.y() >= rect.maxY() - boundariesWidth)
1172 pos.setY(rect.maxY() - boundariesWidth - 1);
1175 OwnPtr<WebCore::VisiblePosition> position = adoptPtr(new WebCore::VisiblePosition(focusedFrame->visiblePositionForPoint(pos)));
1176 WebCore::Position extent = frameSelection->extent();
1178 WebCore::Node* newSelectionStartNode = position->deepEquivalent().deprecatedNode();
1180 // both start and end nodes should be in the same area type: both should be editable or both should be not editable
1181 // Check if the new position is before the extent's position
1182 if (newSelectionStartNode
1183 && selectionEndNode->isContentEditable() == newSelectionStartNode->isContentEditable()
1184 && WebCore::comparePositions(position->deepEquivalent(), extent) < 0) {
1185 // Change the 'base' and 'extent' positions to 'start' and 'end' positions.
1186 // We do it, because without this, the other modification of the selection
1187 // would destroy the 'start' and/or 'end' positions and set them to
1188 // the 'base'/'extent' positions accordingly
1189 WebCore::VisibleSelection sel(frameSelection->start(), frameSelection->end());
1190 frameSelection->setSelection(sel);
1192 bool oldProhibitsScrolling = focusedFrame->view()->prohibitsScrolling();
1193 focusedFrame->view()->setProhibitsScrolling(true);
1195 frameSelection->setBase(*position);
1197 focusedFrame->view()->setProhibitsScrolling(oldProhibitsScrolling);
1198 // This forces webkit to show selection
1199 // m_coreFrame->invalidateSelection();
1206 void WebPage::setRightSelection(const WebCore::IntPoint& point, bool& result)
1210 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1211 WebCore::FrameSelection* frameSelection = focusedFrame->selection();
1213 if (!frameSelection->isRange())
1216 WebCore::Node* selectionStartNode = frameSelection->start().deprecatedNode();
1217 if (!selectionStartNode || !selectionStartNode->renderer())
1220 FrameView* frameView = focusedFrame->view();
1224 WebCore::IntPoint pos = frameView->windowToContents(point);
1225 if (selectionStartNode->rendererIsEditable() && !selectionStartNode->rendererIsRichlyEditable()) {
1226 const int boundariesWidth = 2;
1228 WebCore::IntRect rect = frameSelection->caretRenderer()->absoluteBoundingBoxRect(true);
1229 // here we cheat input field that we actually are just inside of if
1230 if (pos.y() < rect.y() + boundariesWidth)
1231 pos.setY(rect.y() + boundariesWidth);
1232 else if (pos.y() >= rect.maxY() - boundariesWidth)
1233 pos.setY(rect.maxY() - boundariesWidth - 1);
1236 OwnPtr<WebCore::VisiblePosition> position = adoptPtr(new WebCore::VisiblePosition(focusedFrame->visiblePositionForPoint(pos)));
1237 WebCore::Position base = frameSelection->base();
1239 WebCore::Node* newSelectionEndNode = position->deepEquivalent().deprecatedNode();
1241 // both start and end nodes should be in the same area type: both should be editable or both should be not editable
1242 // Check if the new position is after the base's position
1243 if (newSelectionEndNode
1244 && selectionStartNode->isContentEditable() == newSelectionEndNode->isContentEditable()
1245 && WebCore::comparePositions(position->deepEquivalent(), base) > 0) {
1246 // Change the 'base' and 'extent' positions to 'start' and 'end' positions.
1247 // We do it, because without this, the other modifications of the selection
1248 // would destroy the 'start' and/or 'end' positions and set them to
1249 // the 'base'/'extent' positions accordingly
1251 WebCore::VisibleSelection sel(frameSelection->start(), frameSelection->end());
1252 frameSelection->setSelection(sel);
1254 bool oldProhibitsScrolling = focusedFrame->view()->prohibitsScrolling();
1255 focusedFrame->view()->setProhibitsScrolling(true);
1257 frameSelection->setExtent(*position);
1259 focusedFrame->view()->setProhibitsScrolling(oldProhibitsScrolling);
1265 void WebPage::getSelectionHandlers(IntRect& leftRect, IntRect& rightRect)
1267 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1268 if (!focusedFrame->selection()->isRange())
1271 // Is this check necessary? Leaving it for safety.
1272 WebCore::RenderView* root = focusedFrame->contentRenderer();
1276 RefPtr<WebCore::Range> selectedRange = focusedFrame->selection()->toNormalizedRange();
1278 Vector<WebCore::IntRect> rects;
1279 selectedRange->textRects(rects, true);
1281 unsigned size = rects.size();
1283 leftRect = rects[0];
1284 rightRect = rects[size-1];
1285 // prevent from selecting zero-length selection
1286 if (leftRect.x() == rightRect.x() + rightRect.width()
1287 && leftRect.y() == rightRect.y())
1290 FrameView* frameView = focusedFrame->view();
1294 leftRect = frameView->contentsToWindow(leftRect);
1295 rightRect = frameView->contentsToWindow(rightRect);
1299 void WebPage::getSelectionText(String& result)
1301 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1302 result = focusedFrame->editor()->selectedText();
1305 void WebPage::selectionRangeClear(bool& result)
1309 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1310 WebCore::FrameSelection* frameSelection = focusedFrame->selection();
1311 if (!frameSelection)
1314 if (frameSelection->isRange()) {
1315 if (frameSelection->isContentEditable()) {
1316 WebCore::VisiblePosition visiblePos(frameSelection->extent());
1317 if (visiblePos.isNull())
1319 WebCore::VisibleSelection newSelection = WebCore::VisibleSelection(visiblePos);
1320 frameSelection->setSelection(newSelection, WebCore::CharacterGranularity);
1321 frameSelection->setCaretBlinkingSuspended(false);
1323 frameSelection->clear();
1330 #endif // #if OS(TIZEN)
1332 } // namespace WebKit