93530d1784b8d6c0d1fc84787165f232f8f8866d
[framework/web/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/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>
44
45 #if OS(TIZEN)
46 #include "Arguments.h"
47 #include "GraphicsContext.h"
48 #include "WebCoreArgumentCoders.h"
49 #include "WebFrame.h"
50 #include "WebImage.h"
51 #include "WebPageProxyMessages.h"
52 #include <WebCore/FrameView.h>
53
54 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION)
55 #include <WebCore/HTMLInputElement.h>
56 #include <WebCore/HTMLNames.h>
57 #endif
58
59 #if ENABLE(TIZEN_MULTIPLE_SELECT)
60 #include "WebPopupMenu.h"
61 #include <WebCore/PopupMenuClient.h>
62 #endif
63
64 #if ENABLE(TIZEN_MOBILE_WEB_PRINT)
65 #include <WebCore/PlatformContextCairo.h>
66 #endif
67
68 #if ENABLE(TIZEN_CLIPBOARD) || ENABLE(TIZEN_PASTEBOARD)
69 #include <WebCore/ClipboardTizen.h>
70 #endif
71
72 #if ENABLE(TIZEN_PASTEBOARD)
73 #include <WebCore/Pasteboard.h>
74 #endif
75
76 #if ENABLE(TIZEN_WEBKIT2_REMOTE_WEB_INSPECTOR)
77 #include "WebInspectorServerEfl.h"
78 #endif
79
80 #if ENABLE(TIZEN_WEB_STORAGE)
81 #include <WebCore/GroupSettings.h>
82 #include <WebCore/PageGroup.h>
83 #endif
84
85 #if ENABLE(TIZEN_PLUGIN_SUSPEND_RESUME)
86 #include "PluginView.h"
87 #endif
88
89 #if ENABLE(TIZEN_PREFERENCE)
90 #include "WebPreferencesStore.h"
91 #include <WebCore/Settings.h>
92 #endif
93
94 #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
95 #include <WebCore/HTMLFrameOwnerElement.h>
96 #include <WebCore/HTMLImageElement.h>
97 #endif
98
99 #if ENABLE(TIZEN_DEVICE_ORIENTATION)
100 #include "DeviceMotionClientTizen.h"
101 #include "DeviceOrientationClientTizen.h"
102 #endif
103
104 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION_ON_UI_SIDE)
105 #include "RenderLayer.h"
106 #include "WebGraphicsLayer.h"
107 #include <WebCore/RenderView.h>
108 #endif
109
110 #if ENABLE(TIZEN_ISF_PORT)
111 #include <WebCore/Text.h>
112 #include <WebCore/EditorClient.h>
113 #endif
114
115 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION) || ENABLE(TIZEN_WEBKIT2_FORM_DATABASE)
116 #include "EditorClient.h"
117 #endif
118
119 #if ENABLE(TIZEN_DATALIST_ELEMENT)
120 #include "HTMLCollection.h"
121 #include "HTMLDataListElement.h"
122 #include "HTMLOptionElement.h"
123 #endif
124
125 #if ENABLE(TIZEN_STYLE_SCOPED)
126 #include <WebCore/RuntimeEnabledFeatures.h>
127 #endif
128
129 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
130 #include "htmlediting.h"
131 #endif
132
133 #if ENABLE(TIZEN_LINK_MAGNIFIER)
134 #include "LinkMagnifier.h"
135 #endif
136
137 #if ENABLE(TIZEN_SCREEN_READER)
138 #include "WebEventConversion.h"
139 #endif
140
141 #if ENABLE(TIZEN_CSP)
142 #include <WebCore/ContentSecurityPolicy.h>
143 #endif
144
145 #if ENABLE(TIZEN_OFFLINE_PAGE_SAVE)
146 #include "WebPageSerializerTizen.h"
147 #endif
148 #endif // #if OS(TIZEN)
149
150 using namespace WebCore;
151
152 namespace WebKit {
153
154 void WebPage::platformInitialize()
155 {
156 #if ENABLE(TIZEN_DEVICE_ORIENTATION)
157     WebCore::provideDeviceMotionTo(m_page.get(), new DeviceMotionClientTizen);
158     WebCore::provideDeviceOrientationTo(m_page.get(), new DeviceOrientationClientTizen);
159 #endif
160 #if ENABLE(TIZEN_ISF_PORT)
161     m_isSettingComposition = false;
162 #endif
163 }
164
165 #if ENABLE(TIZEN_PREFERENCE)
166 void WebPage::platformPreferencesDidChange(const WebPreferencesStore& store)
167 {
168     Settings* settings = m_page->settings();
169     settings->setInteractiveFormValidationEnabled(store.getBoolValueForKey(WebPreferencesKey::interactiveFormValidationEnabledKey()));
170     settings->setViewWidth(store.getUInt32ValueForKey(WebPreferencesKey::viewWidthKey()));
171     settings->setViewHeight(store.getUInt32ValueForKey(WebPreferencesKey::viewHeightKey()));
172     settings->setUsesEncodingDetector(store.getBoolValueForKey(WebPreferencesKey::usesEncodingDetectorKey()));
173 #if ENABLE(TIZEN_LOAD_REMOTE_IMAGES)
174     settings->setLoadRemoteImages(store.getBoolValueForKey(WebPreferencesKey::loadRemoteImagesKey()));
175 #endif
176 #if ENABLE(TIZEN_ISF_PORT)
177     settings->setEnableDefaultKeypad(store.getBoolValueForKey(WebPreferencesKey::defaultKeypadEnabledKey()));
178 #endif
179 #if ENABLE(TIZEN_STYLE_SCOPED)
180     WebCore::RuntimeEnabledFeatures::setStyleScopedEnabled(store.getBoolValueForKey(WebPreferencesKey::styleScopedEnabledKey()));
181 #endif
182 #if ENABLE(TIZEN_WEB_AUDIO)
183     settings->setWebAudioEnabled(true);
184 #endif
185 }
186 #else
187 void WebPage::platformPreferencesDidChange(const WebPreferencesStore&)
188 {
189     notImplemented();
190 }
191 #endif // #if ENABLE(TIZEN_PREFERENCE)
192
193 static inline void scroll(Page* page, ScrollDirection direction, ScrollGranularity granularity)
194 {
195     page->focusController()->focusedOrMainFrame()->eventHandler()->scrollRecursively(direction, granularity);
196 }
197
198 bool WebPage::performDefaultBehaviorForKeyEvent(const WebKeyboardEvent& keyboardEvent)
199 {
200     notImplemented();
201     return false;
202 }
203
204 bool WebPage::platformHasLocalDataForURL(const KURL&)
205 {
206     notImplemented();
207     return false;
208 }
209
210 String WebPage::cachedResponseMIMETypeForURL(const KURL&)
211 {
212     notImplemented();
213     return String();
214 }
215
216 bool WebPage::platformCanHandleRequest(const ResourceRequest&)
217 {
218     notImplemented();
219     return true;
220 }
221
222 String WebPage::cachedSuggestedFilenameForURL(const KURL&)
223 {
224     notImplemented();
225     return String();
226 }
227
228 PassRefPtr<SharedBuffer> WebPage::cachedResponseDataForURL(const KURL&)
229 {
230     notImplemented();
231     return 0;
232 }
233
234 const char* WebPage::interpretKeyEvent(const KeyboardEvent* event)
235 {
236     ASSERT(event->type() == eventNames().keydownEvent || event->type() == eventNames().keypressEvent);
237
238     if (event->type() == eventNames().keydownEvent)
239         return getKeyDownCommandName(event);
240
241     return getKeyPressCommandName(event);
242 }
243
244 void WebPage::setThemePath(const String& themePath)
245 {
246     WebCore::RenderThemeEfl* theme = static_cast<WebCore::RenderThemeEfl*>(m_page->theme());
247     theme->setThemePath(themePath);
248 }
249
250 #if OS(TIZEN)
251
252 #if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
253 IntSize WebPage::contentsSize() const
254 {
255     FrameView* frameView = m_page->mainFrame()->view();
256     if (!frameView)
257         return IntSize(0, 0);
258
259     return frameView->contentsSize();
260 }
261 #endif
262
263 void WebPage::scrollMainFrameBy(const IntSize& scrollOffset)
264 {
265     m_page->mainFrame()->view()->scrollBy(scrollOffset);
266 }
267
268 void WebPage::scrollMainFrameTo(const IntPoint& scrollPosition)
269 {
270     m_page->mainFrame()->view()->setScrollPosition(scrollPosition);
271 }
272
273 void WebPage::createSnapshot(const IntRect rect, float scaleFactor, ShareableBitmap::Handle& snapshotHandle)
274 {
275     FrameView* frameView = m_mainFrame->coreFrame()->view();
276     if (!frameView)
277         return;
278
279     RefPtr<WebImage> snapshotImage = scaledSnapshotInViewCoordinates(rect, scaleFactor, ImageOptionsShareable);
280     if (!snapshotImage || !snapshotImage->bitmap())
281         return;
282
283     snapshotImage->bitmap()->createHandle(snapshotHandle);
284 }
285
286 void WebPage::requestUpdateFormNavigation()
287 {
288     Frame* frame = m_page->focusController()->focusedOrMainFrame();
289     if (!frame)
290         return;
291
292     Document* document = frame->document();
293     if (!document)
294         return;
295
296     Node* focusedNode = document->focusedNode();
297
298     Vector<RefPtr<Node> > focusableNodes;
299     document->getFocusableNodes(focusableNodes);
300
301     int formElementCount = 0;
302     int currentNodeIndex = -1;
303     const Vector<RefPtr<Node> >::iterator end = focusableNodes.end();
304     for (Vector<RefPtr<Node> >::iterator it = focusableNodes.begin(); it != end; ++it) {
305         AtomicString nodeName = (*it).get()->nodeName();
306         if (equalIgnoringCase(nodeName, "SELECT")
307             || (equalIgnoringCase(nodeName, "INPUT")
308                 && !equalIgnoringCase((*it).get()->toInputElement()->type(), "CHECKBOX")
309                 && !equalIgnoringCase((*it).get()->toInputElement()->type(), "RADIO")
310                 && !equalIgnoringCase((*it).get()->toInputElement()->type(), "SUBMIT")
311                 )
312             ) {
313             if ((*it).get() == focusedNode)
314                 currentNodeIndex = formElementCount;
315             formElementCount++;
316         }
317     }
318
319     if (currentNodeIndex == -1)
320         return;
321
322     send(Messages::WebPageProxy::UpdateFormNavigation(formElementCount, currentNodeIndex));
323 }
324
325 void WebPage::moveFocus(int newIndex)
326 {
327     Frame* frame = m_page->focusController()->focusedOrMainFrame();
328     if (!frame)
329         return;
330
331     Document* document = frame->document();
332     if (!document)
333         return;
334
335     Vector<RefPtr<Node> > focusableNodes;
336     document->getFocusableNodes(focusableNodes);
337
338     int index = 0;
339     const Vector<RefPtr<Node> >::iterator end = focusableNodes.end();
340     for (Vector<RefPtr<Node> >::iterator it = focusableNodes.begin(); it != end; ++it) {
341         AtomicString nodeName = (*it).get()->nodeName();
342         if (equalIgnoringCase(nodeName, "SELECT")) {
343             if (index == newIndex) {
344                 (*it).get()->setFocus();
345                 LayoutPoint position = LayoutPoint(0, 0);
346                 PlatformMouseEvent event(flooredIntPoint(position), flooredIntPoint(position), LeftButton, PlatformEvent::MouseMoved, 1, false, false, false, false, 0);
347                 (*it).get()->dispatchMouseEvent(event, "mousedown", 0, 0);
348             }
349             index++;
350         } else if (equalIgnoringCase(nodeName, "INPUT")
351             && !equalIgnoringCase((*it).get()->toInputElement()->type(), "CHECKBOX")
352             && !equalIgnoringCase((*it).get()->toInputElement()->type(), "RADIO")
353             ) {
354             if (index == newIndex) {
355                 HTMLInputElement* elem = (*it).get()->toInputElement();
356                 elem->focus();
357             }
358             index++;
359         }
360     }
361 }
362
363 #if ENABLE(TIZEN_MOBILE_WEB_PRINT)
364 #define INCH_TO_MM 25.4
365 #define INCH_TO_POINTS 72.0
366
367 void WebPage::createPagesToPDF(const IntSize& surfaceSize, const IntSize& contentsSize, const String& fileName)
368 {
369     FrameView* frameView = m_mainFrame->coreFrame()->view();
370     if (!frameView)
371         return;
372
373     RefPtr<WebImage> pageshotImage = WebImage::create(contentsSize, ImageOptionsShareable);
374     if (!pageshotImage->bitmap())
375         return;
376
377     double pdfWidth = (double)surfaceSize.width() / INCH_TO_MM * INCH_TO_POINTS;
378     double pdfHeight = (double)surfaceSize.height() / INCH_TO_MM * INCH_TO_POINTS;
379     double scaleFactorPdf = 1.0;
380     if (contentsSize.width() > pdfWidth)
381         scaleFactorPdf = pdfWidth / (double)contentsSize.width();
382
383     OwnPtr<WebCore::GraphicsContext> graphicsContext = pageshotImage->bitmap()->createGraphicsContextForPdfSurface(fileName, pdfWidth, pdfHeight);
384     graphicsContext->scale(FloatSize(scaleFactorPdf, scaleFactorPdf));
385
386     frameView->updateLayoutAndStyleIfNeededRecursive();
387
388     int pageNumber = ((contentsSize.height() * scaleFactorPdf) / pdfHeight) + 1;
389     float paintY = 0.0;
390
391     PaintBehavior oldBehavior = frameView->paintBehavior();
392     frameView->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
393     for (int i = 0; i < pageNumber; i++) {
394         IntRect paintRect(0, (int)paintY, contentsSize.width(), (int)(pdfHeight / scaleFactorPdf));
395
396         frameView->paint(graphicsContext.get(), paintRect);
397         cairo_show_page(graphicsContext->platformContext()->cr());
398         graphicsContext->translate(0, -ceil(pdfHeight / scaleFactorPdf));
399         paintY += (pdfHeight / scaleFactorPdf);
400     }
401     frameView->setPaintBehavior(oldBehavior);
402
403     pageshotImage.release();
404 }
405 #endif
406
407 void WebPage::confirmComposition(const String& compositionString)
408 {
409     Frame* frame = m_page->focusController()->focusedOrMainFrame();
410     if (!frame || !frame->editor()->canEdit())
411         return;
412     frame->editor()->confirmComposition(compositionString);
413 #if ENABLE(TIZEN_ISF_PORT)
414     updateCursorOffset();
415 #endif
416 }
417
418 void WebPage::setComposition(const String& compositionString, const Vector<WebCore::CompositionUnderline>& underlines, uint64_t cursorPosition)
419 {
420     Frame* frame = m_page->focusController()->focusedOrMainFrame();
421     if (!frame || !frame->editor()->canEdit())
422         return;
423 #if ENABLE(TIZEN_ISF_PORT)
424     if (frame->selection()->rootEditableElement()) {
425         HTMLTextFormControlElement* textFormControl = toTextFormControl(frame->selection()->rootEditableElement()->shadowAncestorNode());
426         if (textFormControl && textFormControl->maxLength() >= 0) {
427             unsigned availableLength = textFormControl->maxLength() - textFormControl->value().length();
428             if (frame->editor()->hasComposition())
429                 availableLength += (frame->editor()->compositionEnd() - frame->editor()->compositionStart());
430             if (!availableLength)
431                 return;
432
433             if (availableLength < compositionString.length()) {
434                 String newCompositionString = compositionString.substring(0, availableLength);
435                 Vector<CompositionUnderline> newUnderlines;
436                 size_t numUnderlines = underlines.size();
437                 for (size_t index = 0; index < numUnderlines; ++index) {
438                     if (underlines[index].startOffset < availableLength) {
439                         newUnderlines.append(underlines[index]);
440                         if (newUnderlines.last().endOffset > availableLength)
441                             newUnderlines.last().endOffset = availableLength;
442                     }
443                 }
444                 frame->editor()->setComposition(newCompositionString, newUnderlines, cursorPosition, 0);
445                 return;
446             }
447         }
448     }
449     m_isSettingComposition = true;
450 #endif
451     frame->editor()->setComposition(compositionString, underlines, cursorPosition, 0);
452 #if ENABLE(TIZEN_ISF_PORT)
453     m_isSettingComposition = false;
454     updateCursorOffset();
455 #endif
456 }
457
458 #if ENABLE(TIZEN_TEXT_CARET_HANDLING_WK2)
459 bool WebPage::setCaretPosition(const WebCore::IntPoint& pos)
460 {
461     Frame* frame = m_page->focusController()->focusedOrMainFrame();
462     if (!frame)
463         return false;
464
465     WebCore::FrameSelection* controller = frame->selection();
466     if (!controller)
467         return false;
468
469     FrameView* frameView = frame->view();
470     if (!frameView)
471         return false;
472
473     WebCore::IntPoint point = m_page->mainFrame()->view()->windowToContents(pos);
474     WebCore::HitTestResult result = m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(point, /*allowShadowContent*/ true, /*ignoreClipping*/ true);
475     if (result.scrollbar())
476         return false;
477
478     WebCore::Node* innerNode = result.innerNode();
479
480     if (!innerNode || !innerNode->renderer())
481         return false;
482
483     WebCore::VisiblePosition visiblePos;
484
485     // we check if content is richly editable - because those input field behave other than plain text ones
486     // sometimes they may consists a node structure and they need special approach
487     if (innerNode->rendererIsRichlyEditable()) {
488         // point gets inner node local coordinates
489         point = flooredIntPoint(result.localPoint());
490         WebCore::IntRect rect = innerNode->renderer()->absoluteBoundingBoxRect(true);
491
492         // it is not the best way to do this, but it is not as slow and it works - so maybe in the future someone
493         // will have a better idea how to solve it
494         // here we are getting innerNode from HitTestResult - unfortunately this is a kind of high level node
495         // in the code below I am trying to obtain low level node - #text - to get its coordinates and size
496
497         // all those getting nodes rects are needed to bypass WebCore's methods of positioning caret when user
498         // is clicking outside a node - and cheat WebCore telling it that actually we clicked into input field
499         // node, not outside of it
500         WebCore::Node* deepInnerNode = innerNode->renderer()->positionForPoint(point).deepEquivalent().deprecatedNode();
501
502         if (!deepInnerNode || !deepInnerNode->renderer())
503             return false;
504
505         // so we get a base node rectange
506         WebCore::IntRect deepNodeRect = deepInnerNode->renderer()->absoluteBoundingBoxRect(true);
507
508         // we modify our local point to adjust it to base node local coordinates
509         point.move(rect.x() - deepNodeRect.x(), rect.y() - deepNodeRect.y());
510
511         // if we are outside the rect we cheat, that we are just inside of it
512         if (point.y() < 0)
513             point.setY(0);
514         else if (point.y() >= deepNodeRect.height())
515             point.setY(deepNodeRect.height() - 1);
516
517         // visible position created - caret ready to set
518         visiblePos = deepInnerNode->renderer()->positionForPoint(point);
519         if (visiblePos.isNull())
520             return false;
521     } else {
522         // for plain text input fields we can get only a caret bounding box
523         if (!controller->isCaret() || !controller->caretRenderer())
524             return false;
525
526         const WebCore::Node* node = controller->start().deprecatedNode();
527         if (!node || !node->renderer())
528             return false;
529
530         WebCore::IntRect rect = controller->caretRenderer()->absoluteBoundingBoxRect(true);
531
532 // FIXME: The below codes should be updated to apply the positon of focusedFrame.
533 #if 0
534         // here we also cheat input field that we actually are just inside of if
535         if (point.x() < rect.x())
536             point.setX(rect.x());
537         else if (point.x() > rect.maxX())
538             point.setX(rect.maxX());
539
540         const int boundariesWidth = 2;
541         if (point.y() < rect.y() + boundariesWidth)
542             point.setY(rect.y() + boundariesWidth);
543         else if (point.y() >= rect.maxY() - boundariesWidth)
544             point.setY(rect.maxY() - boundariesWidth - 1);
545 #endif
546
547         // hit test with fake (adjusted) coordinates
548         WebCore::IntPoint hitTestPoint = m_page->mainFrame()->view()->windowToContents(point);
549         WebCore::HitTestResult newResult = m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(hitTestPoint, /*allowShadowContent*/ true, /*ignoreClipping*/ true);
550
551         if (!newResult.isContentEditable())
552             return false;
553
554         WebCore::Node* newInnerNode = newResult.innerNode();
555
556         if (!newInnerNode || !newInnerNode->renderer())
557             return false;
558
559         // visible position created
560         visiblePos = newInnerNode->renderer()->positionForPoint(newResult.localPoint());
561         if (visiblePos.isNull())
562             return false;
563     }
564
565     // create visible selection from visible position
566     WebCore::VisibleSelection newSelection = WebCore::VisibleSelection(visiblePos);
567     controller->setSelection(newSelection, WebCore::CharacterGranularity);
568     // after setting selection caret blinking is suspended by default so we are unsuspedning it
569     controller->setCaretBlinkingSuspended(false);
570
571     return true;
572 }
573
574 void WebPage::getCaretPosition(WebCore::IntRect& rect)
575 {
576     Frame* frame = m_page->focusController()->focusedOrMainFrame();
577     if (!frame)
578         return;
579
580     WebCore::FrameSelection* controller = frame->selection();
581     if (!controller)
582         return;
583
584     WebCore::Node* node = controller->start().deprecatedNode();
585     if (!node || !node->renderer() || !node->isContentEditable())
586         return;
587
588     if (controller->isCaret()) {
589         FrameView* frameView = frame->view();
590         if (!frameView)
591             return;
592
593         rect = frameView->contentsToWindow(controller->absoluteCaretBounds());
594     }
595 }
596 #endif
597
598 #if ENABLE(TIZEN_ISF_PORT)
599 void WebPage::updateCursorOffset()
600 {
601     int offset;
602     getCursorOffset(offset);
603     send(Messages::WebPageProxy::UpdateCursorOffset(offset));
604 }
605
606 void WebPage::didCancelComposition(Node* valueChangedNode)
607 {
608     if (m_isSettingComposition)
609         return;
610
611     Frame* frame = m_page->focusController()->focusedOrMainFrame();
612     if (!frame || !valueChangedNode->containsIncludingShadowDOM(frame->editor()->compositionNode()))
613         return;
614
615     frame->editor()->cancelComposition();
616     send(Messages::WebPageProxy::DidCancelComposition());
617 }
618
619 void WebPage::getCursorOffset(int& offset)
620 {
621     offset = 0;
622     Frame* frame = m_page->focusController()->focusedOrMainFrame();
623     if (!frame || !frame->editor()->canEdit())
624         return;
625
626     Position base = frame->selection()->base();
627     Node* baseNode = base.containerNode();
628     if (baseNode)
629         offset = baseNode->isTextNode() ? base.offsetInContainerNode() : 0;
630 }
631
632 void WebPage::getSurroundingTextAndCursorOffset(String& text, int& offset)
633 {
634     text = String();
635     offset = 0;
636
637     Frame* frame = m_page->focusController()->focusedOrMainFrame();
638     if (!frame || !frame->editor()->canEdit())
639         return;
640
641     Position base = frame->selection()->base();
642     Node* baseNode = base.containerNode();
643     if (baseNode && baseNode->isTextNode()) {
644         text = baseNode->textContent();
645         offset = base.offsetInContainerNode();
646     }
647 }
648
649 void WebPage::getSelectionRect(bool isOnlyEditable, IntRect& rect)
650 {
651     rect = IntRect();
652
653     Frame* frame = m_page->focusController()->focusedFrame();
654     if (!frame || !frame->view())
655         return;
656
657     FrameSelection* selection = frame->selection();
658     Node* node = selection->start().deprecatedNode();
659     if (!node || !node->renderer() || (isOnlyEditable && !node->isContentEditable()))
660         return;
661
662     if (selection->isCaret())
663         rect = frame->view()->contentsToWindow(selection->absoluteCaretBounds());
664     else if (selection->isRange())
665         rect = frame->view()->contentsToWindow(enclosingIntRect(selection->bounds()));
666 }
667
668 void WebPage::deleteSurroundingText(int offset, int count)
669 {
670     Frame* frame = m_page->focusController()->focusedOrMainFrame();
671     if (!frame || !frame->editor()->canEdit())
672         return;
673
674     Position base(frame->selection()->base());
675     offset += base.offsetInContainerNode();
676     base.moveToOffset(offset);
677     Position extent(base);
678     extent.moveToOffset(offset + count);
679     VisibleSelection selection(base, extent);
680     if (!selection.isRange())
681         return;
682
683     frame->selection()->setSelection(selection);
684     frame->editor()->deleteWithDirection(DirectionBackward, CharacterGranularity, false, true);
685 }
686 #endif
687
688 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION) || ENABLE(TIZEN_WEBKIT2_FORM_DATABASE)
689 void WebPage::setFocusedInputElementValue(const String& inputValue)
690 {
691     Frame* frame = m_page->focusController()->focusedOrMainFrame();
692     if (!frame || !frame->document() || !frame->document()->focusedNode())
693         return;
694
695     HTMLInputElement* inputElement = frame->document()->focusedNode()->toInputElement();
696     if (!inputElement)
697         return;
698
699     inputElement->toNode()->dispatchFocusEvent(0);
700     inputElement->setValue(inputValue, DispatchChangeEvent);
701
702     updateCursorOffset();
703 }
704
705 void  WebPage::getFocusedInputElementValue(String& inputValue)
706 {
707     inputValue = String();
708
709     Frame* frame = m_page->focusController()->focusedOrMainFrame();
710     if (!frame || !frame->document() || !frame->document()->focusedNode())
711         return;
712
713     HTMLInputElement* inputElement = frame->document()->focusedNode()->toInputElement();
714     if (!inputElement)
715         return;
716
717     inputValue = inputElement->value();
718 }
719 #endif
720
721 #if ENABLE(TIZEN_DATALIST_ELEMENT)
722 void WebPage::getFocusedInputElementDataList(Vector<String>& optionList)
723 {
724     Frame* frame = m_page->focusController()->focusedOrMainFrame();
725     if (!frame || !frame->document())
726         return;
727
728     Node* node = frame->document()->focusedNode();
729     if (!node)
730         return;
731
732     HTMLInputElement* input = node->toInputElement();
733     if (!input)
734         return;
735
736     HTMLDataListElement* dataList = static_cast<HTMLDataListElement*>(input->list());
737     if (!dataList)
738         return;
739
740     RefPtr<HTMLCollection> options = static_cast<HTMLDataListElement*>(dataList)->options();
741     for (unsigned i = 0; Node* node = options->item(i); i++) {
742         HTMLOptionElement* optionElement = static_cast<HTMLOptionElement*>(node);
743         String value = optionElement->value();
744         optionList.append(value);
745     }
746 }
747 #endif
748
749 #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
750 static IntRect getNodeRect(Node* node, Node* focusableNode, bool isImage)
751 {
752     IntRect rect;
753
754     if (isImage) {
755         bool isReplaced;
756         IntRect imageNodeRect = pixelSnappedIntRect(node->getRect());
757         if (!focusableNode->renderRect(&isReplaced).isEmpty() && imageNodeRect.contains(pixelSnappedIntRect(focusableNode->getRect()))) {
758             // If render rect of focusableNode is empty and rect of imageNode include rect of focusableNode,
759             // we have to get rect of focusableNode.
760             // for example - The rect of google logo image in www.google.com pc site's search result page is bigger than rect of focusableNode.
761             // for example - The rect of category menu image in www.gmarket.co.kr pc site is bigger than rect of focusableNode.
762             rect = pixelSnappedIntRect(focusableNode->getRect());
763         }
764         else {
765             // otherwise we have to get rect of imageNode.
766             // for example - The render rect of images in www.pudelek.pl is empty.
767             // 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.
768             rect = imageNodeRect;
769             focusableNode = node;
770         }
771     } else {
772         // If focusedNode have multiple child nodes, we have to unite rect of child nodes.
773         // for example - links in www.google.com's search result page.
774         IntRect tempRect;
775         for (Node* childNode = focusableNode->firstChild(); childNode; childNode = childNode->traverseNextNode(focusableNode)) {
776             bool isReplaced;
777             if (focusableNode->renderRect(&isReplaced).contains(childNode->getRect()))
778                 tempRect.unite(pixelSnappedIntRect(childNode->getRect()));
779         }
780
781         // If tempRect is empty or rect of focusableNode include tempRect,
782         // we have to get rect of focusableNode.
783         // for example - list menu item in m.naver.com.
784         // otherwise we have to get rect of tempRect.
785         // getRect API do not return correct rect if the node is a container node,
786         // hence using absoluteBoundingBoxRect to get the correct bounding rect.
787         LayoutRect renderRect = focusableNode->renderer() ? focusableNode->renderer()->absoluteBoundingBoxRect() : focusableNode->getRect();
788         if (tempRect.isEmpty() || renderRect.contains(tempRect))
789             rect = pixelSnappedIntRect(renderRect);
790         else
791             rect = tempRect;
792     }
793
794     // We have to get render rect from ancestor node if current rect is empty.
795     // for example - The rect of naver logo image in www.naver.com pc site is empty.
796     bool isReplaced;
797     for (Node* loopNode = focusableNode; loopNode && rect.isEmpty(); loopNode = loopNode->parentNode()) {
798         RenderObject* renderer = loopNode->renderer();
799         if (renderer && renderer->isRoot())
800             break;
801
802         rect = pixelSnappedIntRect(loopNode->renderRect(&isReplaced));
803     }
804
805     Frame* nodeFrame = focusableNode->document()->frame();
806     Node* owner;
807     while (nodeFrame && (owner = nodeFrame->ownerElement())) {
808         rect.moveBy(owner->getRect().pixelSnappedLocation());
809         nodeFrame = owner->document()->frame();
810     }
811
812     // The y position of tab menu item in www.google.com is negative value,
813     // so we do not want to draw focus ring in that case.
814     if ((rect.maxX() < 0) || (rect.maxY() < 0))
815         rect = IntRect();
816
817     return rect;
818 }
819 #endif
820
821 #if ENABLE(TIZEN_WEBKIT2_HIT_TEST)
822 #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
823 static IntRect getFocusedRect(HitTestResult hitTestResult, Page* page)
824 {
825     Node* node = hitTestResult.innerNode();
826     bool isFocusRingDrawable = false;
827     Node* focusableNode = node;
828     while (focusableNode) {
829         RenderObject* renderer = focusableNode->renderer();
830         if (renderer && renderer->isRoot())
831             break;
832
833         if (focusableNode->isFocusable()) {
834             if (focusableNode->isLink()
835                 || focusableNode->hasTagName(HTMLNames::inputTag)
836                 || focusableNode->hasTagName(HTMLNames::selectTag)
837                 || focusableNode->hasTagName(HTMLNames::buttonTag))
838                 isFocusRingDrawable = true;
839             break;
840         }
841
842         focusableNode = focusableNode->parentNode();
843     }
844
845     if (!isFocusRingDrawable)
846         return IntRect();
847
848     return getNodeRect(node, focusableNode, !hitTestResult.absoluteImageURL().isEmpty());
849 }
850 #endif
851
852 void WebPage::hitTestResultAtPoint(const IntPoint& point, int hitTestMode, WebHitTestResult::Data& hitTestResultData)
853 {
854     Frame* frame = m_page->mainFrame();
855     FrameView* frameView = frame->view();
856     if (!frameView)
857         return;
858
859     HitTestResult hitTestResult = frame->eventHandler()->hitTestResultAtPoint(frameView->windowToContents(point), false);
860     hitTestResultData.absoluteImageURL = hitTestResult.absoluteImageURL().string();
861     hitTestResultData.absoluteLinkURL = hitTestResult.absoluteLinkURL().string();
862     hitTestResultData.absoluteMediaURL = hitTestResult.absoluteMediaURL().string();
863     hitTestResultData.linkLabel = hitTestResult.textContent();
864     hitTestResultData.linkTitle = hitTestResult.titleDisplayString();
865 #if ENABLE(TIZEN_DRAG_SUPPORT)
866     hitTestResultData.isDragSupport = hitTestResult.isDragSupport();
867 #endif
868
869     int context = WebHitTestResult::HitTestResultContextDocument;
870
871     if (!hitTestResult.absoluteLinkURL().isEmpty())
872         context |= WebHitTestResult::HitTestResultContextLink;
873     if (!hitTestResult.absoluteImageURL().isEmpty())
874         context |= WebHitTestResult::HitTestResultContextImage;
875     if (!hitTestResult.absoluteMediaURL().isEmpty())
876         context |= WebHitTestResult::HitTestResultContextMedia;
877     if (hitTestResult.isSelected())
878         context |= WebHitTestResult::HitTestResultContextSelection;
879     if (hitTestResult.isContentEditable())
880         context |= WebHitTestResult::HitTestResultContextEditable;
881     if (hitTestResult.innerNonSharedNode() && hitTestResult.innerNonSharedNode()->isTextNode())
882         context |= WebHitTestResult::HitTestResultContextText;
883
884     hitTestResultData.context = context;
885     hitTestResultData.hitTestMode = hitTestMode;
886
887 #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
888     hitTestResultData.focusedRect = getFocusedRect(hitTestResult, m_page.get());
889     if (hitTestResult.innerNode() && hitTestResult.innerNode()->renderer() && hitTestResult.innerNode()->renderer()->style()) {
890         hitTestResultData.focusedColor = hitTestResult.innerNode()->renderer()->style()->tapHighlightColor();
891         if (!hitTestResultData.focusedColor.hasAlpha())
892             hitTestResultData.focusedColor = Color(hitTestResultData.focusedColor.red(), hitTestResultData.focusedColor.green(), hitTestResultData.focusedColor.blue(), RenderStyle::initialTapHighlightColor().alpha());
893     }
894 #endif
895
896     if (hitTestResultData.hitTestMode & WebHitTestResult::HitTestModeNodeData) {
897         WebCore::Node* hitNode = hitTestResult.innerNonSharedNode();
898         if (hitNode) {
899             hitTestResultData.nodeData.nodeValue = hitNode->nodeValue();
900
901             if ((hitTestResultData.context & WebHitTestResult::HitTestResultContextText) && hitNode->parentNode())
902                 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.
903
904             if (hitNode->isElementNode()) {
905                 WebCore::Element* hitElement = static_cast<WebCore::Element*>(hitNode);
906                 if (hitElement) {
907                     hitTestResultData.nodeData.tagName = hitElement->tagName();
908                 }
909             }
910
911             WebCore::NamedNodeMap* namedNodeMap = hitNode->attributes();
912             if (namedNodeMap) {
913                 for (size_t i = 0; i < namedNodeMap->length(); i++) {
914                     const WebCore::Attribute* attribute = namedNodeMap->element()->attributeItem(i);
915                     String key = attribute->name().toString();
916                     String value = attribute->value();
917                     hitTestResultData.nodeData.attributeMap.add(key, value);
918                 }
919             }
920         }
921     }
922
923     if ((hitTestResultData.hitTestMode & WebHitTestResult::HitTestModeImageData) && (hitTestResultData.context & WebHitTestResult::HitTestResultContextImage)) {
924         WebCore::Image* hitImage = hitTestResult.image();
925         if (hitImage && hitImage->data() && hitImage->data()->data()) {
926             hitTestResultData.imageData.data.append(hitImage->data()->data(), hitImage->data()->size());
927             hitTestResultData.imageData.fileNameExtension = hitImage->filenameExtension();
928         }
929     }
930 }
931 #endif
932
933 #if ENABLE(TIZEN_WEB_STORAGE)
934 void WebPage::getStorageQuotaBytes(uint64_t callbackID)
935 {
936     uint32_t quota = m_page->group().groupSettings()->localStorageQuotaBytes();
937     send(Messages::WebPageProxy::DidGetWebStorageQuotaBytes(quota, callbackID));
938 }
939
940 void WebPage::setStorageQuotaBytes(uint32_t quota)
941 {
942     m_page->group().groupSettings()->setLocalStorageQuotaBytes(quota);
943 }
944 #endif
945
946 #if ENABLE(TIZEN_RECORDING_SURFACE_SET)
947 void WebPage::recordingSurfaceSetEnableSet(bool enable)
948 {
949     m_recordingSurfaceSetSettings = enable;
950 }
951 #endif
952
953 #if ENABLE(TIZEN_CLIPBOARD) || ENABLE(TIZEN_PASTEBOARD)
954 void WebPage::setClipboardDataForPaste(const String& data, const String& type)
955 {
956 #if ENABLE(TIZEN_PASTEBOARD)
957     // FIXME: Should move to EditorClient like Clipboard
958     Pasteboard::generalPasteboard()->setDataWithType(data, type);
959 #else
960     Frame* mainFrame = m_page->mainFrame();
961     if (!mainFrame)
962         return;
963
964     mainFrame->editor()->client()->setClipboardDataForPaste(data, type);
965 #endif
966 }
967 #endif
968
969 void WebPage::suspendJavaScriptAndResources()
970 {
971     Frame* mainFrame = m_page->mainFrame();
972     if (!mainFrame)
973         return;
974
975     for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext())
976         frame->document()->suspendScheduledTasks(WebCore::ActiveDOMObject::PageWillBeSuspended);
977     mainFrame->loader()->suspendAllLoaders();
978 }
979
980 void WebPage::resumeJavaScriptAndResources()
981 {
982     Frame* mainFrame = m_page->mainFrame();
983     if (!mainFrame)
984         return;
985
986     for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext())
987         frame->document()->resumeScheduledTasks();
988     mainFrame->loader()->resumeAllLoaders();
989 }
990
991 #if ENABLE(TIZEN_SYNC_REQUEST_ANIMATION_FRAME)
992 void WebPage::suspendAnimationController()
993 {
994     if (!m_suspendedAnimationController) {
995         Frame* mainFrame = m_page->mainFrame();
996         if (!mainFrame)
997             return;
998
999         for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext())
1000             frame->document()->suspendScriptedAnimationControllerCallbacks();
1001
1002         m_suspendedAnimationController = true;
1003     }
1004 }
1005
1006 void WebPage::resumeAnimationController()
1007 {
1008     if (m_suspendedAnimationController) {
1009         Frame* mainFrame = m_page->mainFrame();
1010         if (!mainFrame)
1011             return;
1012
1013         for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext())
1014             frame->document()->resumeScriptedAnimationControllerCallbacks();
1015
1016         m_suspendedAnimationController = false;
1017     }
1018 }
1019 #endif
1020
1021 #if ENABLE(TIZEN_WEBKIT2_REMOTE_WEB_INSPECTOR)
1022 void WebPage::startInspectorServer(uint32_t port,  uint32_t& allocatedPort)
1023 {
1024     bool ret = WebInspectorServerEfl::server()->startServer(port);
1025     if (ret)
1026         allocatedPort = WebInspectorServerEfl::server()->getServerPort();
1027     else
1028         allocatedPort = 0;
1029 }
1030
1031 void WebPage::stopInspectorServer(bool& result)
1032 {
1033     result = WebInspectorServerEfl::server()->stopServer();
1034 }
1035 #endif
1036
1037 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION_ON_UI_SIDE)
1038 void WebPage::scrollOverflowWithTrajectoryVector(const WebCore::FloatPoint& trajectoryVector)
1039 {
1040     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1041     if (!frame)
1042         return;
1043     frame->eventHandler()->scrollOverflow(trajectoryVector);
1044 }
1045 #endif
1046
1047 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
1048 void WebPage::scrollOverflow(const WebCore::FloatPoint& delta, bool& scrolled)
1049 {
1050     scrolled = m_page->focusController()->focusedOrMainFrame()->eventHandler()->scrollOverflow(delta);
1051 }
1052
1053 void WebPage::setPressedNodeAtPoint(const IntPoint& point, bool checkOverflowLayer, bool& pressed, uint32_t& id)
1054 {
1055     RenderObject* renderer = 0;
1056     id = 0;
1057     pressed = m_page->focusController()->focusedOrMainFrame()->eventHandler()->setMousePressNodeAtPoint(point, checkOverflowLayer, renderer);
1058 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION_ON_UI_SIDE)
1059     if (pressed && renderer)
1060         id = toWebGraphicsLayer(renderer->enclosingLayer()->layerForScrollingContents())->id();
1061 #endif
1062 }
1063 #endif
1064
1065 void WebPage::executeEditCommandWithArgument(const String& commandName, const String& argument)
1066 {
1067     executeEditingCommand(commandName, argument);
1068 }
1069
1070 #if ENABLE(TIZEN_PLUGIN_SUSPEND_RESUME)
1071 void WebPage::suspendPlugin()
1072 {
1073     for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
1074         FrameView* view = frame->view();
1075         if (!view)
1076             continue;
1077
1078         const HashSet<RefPtr<Widget> >* children = view->children();
1079         ASSERT(children);
1080
1081         HashSet<RefPtr<Widget> >::const_iterator end = children->end();
1082         for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) {
1083             Widget* widget = (*it).get();
1084             if (widget->isPluginViewBase()) {
1085                 PluginView* pluginView = static_cast<PluginView*>(widget);
1086                 if (pluginView)
1087                     pluginView->suspendPlugin();
1088             }
1089         }
1090     }
1091 }
1092
1093 void WebPage::resumePlugin()
1094 {
1095     for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
1096         FrameView* view = frame->view();
1097         if (!view)
1098             continue;
1099
1100         const HashSet<RefPtr<Widget> >* children = view->children();
1101         ASSERT(children);
1102
1103         HashSet<RefPtr<Widget> >::const_iterator end = children->end();
1104         for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) {
1105             Widget* widget = (*it).get();
1106             if (widget->isPluginViewBase()) {
1107                 PluginView* pluginView = static_cast<PluginView*>(widget);
1108                 if (pluginView)
1109                     pluginView->resumePlugin();
1110             }
1111         }
1112     }
1113 }
1114 #endif
1115
1116 #if ENABLE(TIZEN_WEBKIT2_GET_TEXT_STYLE_FOR_SELECTION)
1117 void WebPage::getTextStyleStateForSelection()
1118 {
1119     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1120
1121     int underlineState = frame->editor()->selectionHasStyle(CSSPropertyWebkitTextDecorationsInEffect, "underline");
1122     int italicState = frame->editor()->selectionHasStyle(CSSPropertyFontStyle, "italic");
1123     int boldState = frame->editor()->selectionHasStyle(CSSPropertyFontWeight, "bold");
1124
1125     send(Messages::WebPageProxy::DidGetTextStyleStateForSelection(underlineState, italicState, boldState));
1126 }
1127 #endif
1128
1129 #if ENABLE(TIZEN_MULTIPLE_SELECT)
1130 void WebPage::didChangeSelectedIndexForActivePopupMenuMultiple(Vector<int32_t> newIndex)
1131 {
1132     if (!m_activePopupMenu)
1133         return;
1134
1135     m_activePopupMenu->client()->popupDidHide();
1136
1137     size_t indexSize = newIndex.size();
1138     for (size_t i = 0; i < indexSize; i++)
1139         m_activePopupMenu->didChangeSelectedIndex(newIndex.at(i));
1140
1141 }
1142 #endif
1143
1144 #if ENABLE(TIZEN_OFFLINE_PAGE_SAVE)
1145 void WebPage::startOfflinePageSave(String subresourceFolderName)
1146 {
1147     WebPageSerializerTizen::getSerializedPageContent(this, subresourceFolderName);
1148 }
1149 #endif
1150
1151 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
1152 void WebPage::selectClosestWord(const IntPoint& point, bool isStartedTextSelectionFromOutside, bool& result)
1153 {
1154     result = false;
1155
1156     Frame* mainFrame = m_page->mainFrame();
1157     Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1158
1159     HitTestResult hitTestResult = mainFrame->eventHandler()->hitTestResultAtPoint(m_page->mainFrame()->view()->windowToContents(point), false);
1160
1161     Node* node = hitTestResult.innerNonSharedNode();
1162     if (!node)
1163         return;
1164
1165      Frame* newFocusFrame = node->document()->frame();
1166      if (focusedFrame != newFocusFrame) {
1167          m_page->focusController()->setFocusedFrame(newFocusFrame);
1168          focusedFrame = newFocusFrame;
1169      }
1170
1171 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION)
1172     HTMLInputElement* inputElement = node->toInputElement();
1173 #endif
1174
1175     if (hitTestResult.isContentEditable()) {
1176 #if ENABLE(TIZEN_ISF_PORT)
1177         if (focusedFrame)
1178             didCancelComposition(node);
1179 #endif
1180 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION)
1181         if (!inputElement || (inputElement
1182             && !inputElement->isDateField() && !inputElement->isDateTimeField() && !inputElement->isDateTimeLocalField()
1183             && !inputElement->isMonthField() && !inputElement->isTimeField() && !inputElement->isWeekField())) {
1184             result = setCaretPosition(point);
1185             return;
1186         }
1187 #else
1188         result = setCaretPosition(point);
1189         return;
1190 #endif
1191     }
1192
1193 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION)
1194     if (!node->isTextNode() && !inputElement)
1195 #else
1196     if (!node->isTextNode())
1197 #endif
1198         return;
1199
1200     if (!isStartedTextSelectionFromOutside) {
1201         for (Node* node = hitTestResult.innerNonSharedNode(); node; node = node->parentNode()) {
1202             if (node->isFocusable()) {
1203                 // Text selection shoud not be started when text of <button> tag is selected.
1204                 if (node->hasTagName(HTMLNames::buttonTag))
1205                     return;
1206                 break;
1207             }
1208         }
1209     }
1210
1211     FrameSelection* frameSelection = focusedFrame->selection();
1212
1213     VisiblePosition position = mainFrame->visiblePositionForPoint(point);
1214     VisibleSelection selection(position);
1215
1216     // This changes just the 'start' and 'end' positions of the VisibleSelection
1217     selection.expandUsingGranularity(WordGranularity);
1218
1219     FrameSelection::SetSelectionOptions options = FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle | FrameSelection::DoNotSetFocus;
1220     frameSelection->setSelection(VisibleSelection(selection.start(), selection.end()), options);
1221
1222     if (!frameSelection->isRange())
1223         return;
1224
1225     // This changes just the 'start' and 'end' positions of the VisibleSelection
1226     // Find handlers positions
1227     IntRect leftRect, rightRect;
1228     getSelectionHandlers(leftRect, rightRect);
1229     if (leftRect.size().isZero() && rightRect.size().isZero()) {
1230         // Sometimes there is no selected text, but isNone() returns TRUE
1231         // in this case ewk_frame_selection_handlers_get() returns FALSE and handlers are invalid
1232         // Workaround - clear the selection.
1233         // Better solution would be to modify the ewk_frame_select_closest_word()
1234         // to not select anything in the first place (for example - don't call setSelection()
1235         // if there is nothing under the cursor).
1236         selectionClearAllSelection(m_page->mainFrame());
1237         return;
1238     }
1239
1240     result = true;
1241 }
1242
1243 void WebPage::setLeftSelection(const WebCore::IntPoint& point, bool& result)
1244 {
1245     result = false;
1246
1247     Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1248     WebCore::FrameSelection* frameSelection = focusedFrame->selection();
1249     if (!frameSelection->isRange())
1250         return;
1251
1252     WebCore::Node* selectionEndNode = frameSelection->end().deprecatedNode();
1253     if (!selectionEndNode || !selectionEndNode->renderer())
1254         return;
1255
1256     FrameView* frameView = focusedFrame->view();
1257     if (!frameView)
1258         return;
1259
1260     WebCore::IntPoint pos = frameView->windowToContents(point);
1261     WebCore::IntRect leftRect, rightRect;
1262     getSelectionHandlers(leftRect, rightRect);
1263     if ((rightRect.y() + rightRect.height()) < pos.y())
1264         pos.setY(rightRect.y() + (rightRect.height()/2));
1265
1266     if (selectionEndNode->rendererIsEditable() && !selectionEndNode->rendererIsRichlyEditable()) {
1267         const int boundariesWidth = 2;
1268
1269         WebCore::IntRect rect = frameSelection->caretRenderer()->absoluteBoundingBoxRect(true);
1270         // here we cheat input field that we actually are just inside of if
1271         if (pos.y() < rect.y() + boundariesWidth)
1272             pos.setY(rect.y() + boundariesWidth);
1273         else if (pos.y() >= rect.maxY() - boundariesWidth)
1274             pos.setY(rect.maxY() - boundariesWidth - 1);
1275     }
1276
1277     OwnPtr<WebCore::VisiblePosition> position = adoptPtr(new WebCore::VisiblePosition(focusedFrame->visiblePositionForPoint(pos)));
1278     WebCore::Position extent = frameSelection->extent();
1279
1280     WebCore::Node* newSelectionStartNode = position->deepEquivalent().deprecatedNode();
1281
1282     // both start and end nodes should be in the same area type: both should be editable or both should be not editable
1283     // Check if the new position is before the extent's position
1284     if (newSelectionStartNode
1285         && selectionEndNode->isContentEditable() == newSelectionStartNode->isContentEditable()
1286         && WebCore::comparePositions(position->deepEquivalent(), extent) < 0) {
1287         // Change the 'base' and 'extent' positions to 'start' and 'end' positions.
1288         // We do it, because without this, the other modification of the selection
1289         // would destroy the 'start' and/or 'end' positions and set them to
1290         // the 'base'/'extent' positions accordingly
1291         WebCore::VisibleSelection sel(frameSelection->start(), frameSelection->end());
1292         frameSelection->setSelection(sel);
1293
1294         bool oldProhibitsScrolling = focusedFrame->view()->prohibitsScrolling();
1295         focusedFrame->view()->setProhibitsScrolling(true);
1296
1297         frameSelection->setBase(*position);
1298
1299         focusedFrame->view()->setProhibitsScrolling(oldProhibitsScrolling);
1300         // This forces webkit to show selection
1301         // m_coreFrame->invalidateSelection();
1302
1303         result = true;
1304     }
1305 }
1306
1307
1308 void WebPage::setRightSelection(const WebCore::IntPoint& point, bool& result)
1309 {
1310     result = false;
1311
1312     Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1313     WebCore::FrameSelection* frameSelection = focusedFrame->selection();
1314
1315     if (!frameSelection->isRange())
1316         return;
1317
1318     WebCore::Node* selectionStartNode = frameSelection->start().deprecatedNode();
1319     if (!selectionStartNode || !selectionStartNode->renderer())
1320         return;
1321
1322     FrameView* frameView = focusedFrame->view();
1323     if (!frameView)
1324         return;
1325
1326     WebCore::IntPoint pos = frameView->windowToContents(point);
1327     if (selectionStartNode->rendererIsEditable() && !selectionStartNode->rendererIsRichlyEditable()) {
1328         const int boundariesWidth = 2;
1329
1330         WebCore::IntRect rect = frameSelection->caretRenderer()->absoluteBoundingBoxRect(true);
1331         // here we cheat input field that we actually are just inside of if
1332         if (pos.y() < rect.y() + boundariesWidth)
1333             pos.setY(rect.y() + boundariesWidth);
1334         else if (pos.y() >= rect.maxY() - boundariesWidth)
1335             pos.setY(rect.maxY() - boundariesWidth - 1);
1336     }
1337
1338     OwnPtr<WebCore::VisiblePosition> position = adoptPtr(new WebCore::VisiblePosition(focusedFrame->visiblePositionForPoint(pos)));
1339     WebCore::Position base = frameSelection->base();
1340
1341     WebCore::Node* newSelectionEndNode = position->deepEquivalent().deprecatedNode();
1342
1343     // both start and end nodes should be in the same area type: both should be editable or both should be not editable
1344     // Check if the new position is after the base's position
1345     if (newSelectionEndNode
1346         && selectionStartNode->isContentEditable() == newSelectionEndNode->isContentEditable()
1347         && WebCore::comparePositions(position->deepEquivalent(), base) > 0) {
1348         // Change the 'base' and 'extent' positions to 'start' and 'end' positions.
1349         // We do it, because without this, the other modifications of the selection
1350         // would destroy the 'start' and/or 'end' positions and set them to
1351         // the 'base'/'extent' positions accordingly
1352
1353         WebCore::VisibleSelection sel(frameSelection->start(), frameSelection->end());
1354         frameSelection->setSelection(sel);
1355
1356         bool oldProhibitsScrolling = focusedFrame->view()->prohibitsScrolling();
1357         focusedFrame->view()->setProhibitsScrolling(true);
1358
1359         frameSelection->setExtent(*position);
1360
1361         focusedFrame->view()->setProhibitsScrolling(oldProhibitsScrolling);
1362
1363         result = true;
1364     }
1365 }
1366
1367 void WebPage::getSelectionHandlers(IntRect& leftRect, IntRect& rightRect)
1368 {
1369     Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1370     if (!focusedFrame->selection()->isRange())
1371         return;
1372
1373     // Is this check necessary? Leaving it for safety.
1374     WebCore::RenderView* root = focusedFrame->contentRenderer();
1375     if (!root)
1376         return;
1377
1378     RefPtr<WebCore::Range> selectedRange = focusedFrame->selection()->toNormalizedRange();
1379
1380     Vector<WebCore::IntRect> rects;
1381     selectedRange->textRects(rects, true);
1382
1383     unsigned size = rects.size();
1384     if (size > 0) {
1385         leftRect = rects[0];
1386         rightRect = rects[size-1];
1387
1388         // If selection rect size is greater than editor rect size because of round operation,
1389         // selection rect size should be changed to editor rect size.
1390         if (size == 1) {
1391             Element* selectionRoot = focusedFrame->selection()->rootEditableElement();
1392             if (selectionRoot) {
1393                 WebCore::IntRect editorRect = focusedFrame->view()->contentsToWindow(selectionRoot->getPixelSnappedRect());
1394
1395                 if (leftRect.maxY() > editorRect.maxY()) {
1396                     leftRect.setY(editorRect.y());
1397                     leftRect.setHeight(editorRect.height());
1398                 }
1399
1400                 if (rightRect.maxY() > editorRect.maxY()) {
1401                     rightRect.setY(editorRect.y());
1402                     rightRect.setHeight(editorRect.height());
1403                 }
1404             }
1405         }
1406
1407         // prevent from selecting zero-length selection
1408         if (leftRect.x() == rightRect.x() + rightRect.width()
1409             && leftRect.y() == rightRect.y())
1410             return;
1411
1412         FrameView* frameView = focusedFrame->view();
1413         if (!frameView)
1414             return;
1415
1416         leftRect = frameView->contentsToWindow(leftRect);
1417         rightRect = frameView->contentsToWindow(rightRect);
1418      }
1419 }
1420
1421 void WebPage::getSelectionText(String& result)
1422 {
1423     Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1424     result = focusedFrame->editor()->selectedText();
1425 }
1426
1427 void WebPage::selectionRangeClear(bool& result)
1428 {
1429     result = false;
1430
1431     Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1432     WebCore::FrameSelection* frameSelection = focusedFrame->selection();
1433     if (frameSelection && frameSelection->isRange() && frameSelection->isContentEditable()) {
1434         WebCore::VisiblePosition visiblePos(frameSelection->extent());
1435         if (visiblePos.isNull())
1436             return;
1437         WebCore::VisibleSelection newSelection = WebCore::VisibleSelection(visiblePos);
1438         frameSelection->setSelection(newSelection, WebCore::CharacterGranularity);
1439         frameSelection->setCaretBlinkingSuspended(false);
1440     } else
1441         selectionClearAllSelection(m_page->mainFrame());
1442
1443     result = true;
1444 }
1445
1446 void WebPage::selectionClearAllSelection(Frame* frame)
1447 {
1448     if (!frame)
1449         return;
1450
1451     WebCore::FrameSelection* frameSelection = frame->selection();
1452     if (frameSelection)
1453         frameSelection->clear();
1454
1455     if (!frame->tree())
1456         return;
1457
1458     if (frame->tree()->childCount() > 0) {
1459         if (frame->tree()->firstChild())
1460             selectionClearAllSelection(frame->tree()->firstChild());
1461     } else if (frame->tree()->nextSibling())
1462         selectionClearAllSelection(frame->tree()->nextSibling());
1463 }
1464
1465 #endif
1466
1467 #if ENABLE(TIZEN_LINK_MAGNIFIER)
1468 void WebPage::getLinkMagnifierRect(const IntPoint& position, const IntSize& size)
1469 {
1470     send(Messages::WebPageProxy::DidGetLinkMagnifierRect(position, LinkMagnifier::rect(this, position, size)));
1471 }
1472 #endif
1473
1474 #if ENABLE(TIZEN_SCREEN_READER)
1475 void WebPage::raiseTapEvent(const IntPoint& position, const IntPoint& globalPosition)
1476 {
1477     Frame* frame = m_page->mainFrame();
1478     if (!frame->view())
1479         return;
1480
1481     Vector<WebPlatformTouchPoint> touchPoints;
1482     touchPoints.append(WebPlatformTouchPoint(0, WebPlatformTouchPoint::TouchPressed, globalPosition, position));
1483
1484     WebTouchEvent touchStartEvent(WebEvent::TouchStart, touchPoints, WebEvent::Modifiers(0), ecore_time_get());
1485     if (!frame->eventHandler()->handleTouchEvent(platform(touchStartEvent))) {
1486         WebGestureEvent gestureEvent(WebEvent::GestureSingleTap, position, globalPosition, WebEvent::Modifiers(0), ecore_time_get());
1487         frame->eventHandler()->handleGestureEvent(platform(gestureEvent));
1488     }
1489
1490     touchPoints.at(0).setState(WebPlatformTouchPoint::TouchReleased);
1491     WebTouchEvent touchEndEvent(WebEvent::TouchEnd, touchPoints, WebEvent::Modifiers(0), ecore_time_get());
1492     frame->eventHandler()->handleTouchEvent(platform(touchEndEvent));
1493 }
1494
1495 static void sendScreenReaderFocusRect(WebPage* page, Node* node)
1496 {
1497     bool isImage = false;
1498     if (node->isElementNode()) {
1499         Element* element = static_cast<Element*>(node);
1500         isImage = !element->getAttribute(element->imageSourceAttributeName()).isEmpty();
1501     }
1502
1503     page->send(Messages::WebPageProxy::DidScreenReaderFocusRectChanged(getNodeRect(node, node, isImage)));
1504 }
1505
1506 void WebPage::moveScreenReaderFocus(bool forward, bool& result)
1507 {
1508     if (!m_screenReader)
1509         m_screenReader = ScreenReader::create(this);
1510
1511     if (!m_screenReader->moveFocus(forward)) {
1512         result = false;
1513         send(Messages::WebPageProxy::DidScreenReaderFocusRectChanged(IntRect()));
1514         return;
1515     } else {
1516         result = true;
1517         sendScreenReaderFocusRect(this, m_screenReader->getFocusedNode());
1518     }
1519 }
1520
1521 void WebPage::moveScreenReaderFocusByPoint(const IntPoint& point)
1522 {
1523     if (!m_screenReader)
1524         m_screenReader = ScreenReader::create(this);
1525
1526     if (!m_screenReader->moveFocus(point))
1527         return;
1528
1529     sendScreenReaderFocusRect(this, m_screenReader->getFocusedNode());
1530 }
1531
1532 void WebPage::recalcScreenReaderFocusRect()
1533 {
1534     if (!m_screenReader || !m_screenReader->getFocusedNode())
1535         return;
1536
1537     sendScreenReaderFocusRect(this, m_screenReader->getFocusedNode());
1538 }
1539
1540 void WebPage::updateScreenReaderFocus(Node* willRemoveNode)
1541 {
1542     if (!m_screenReader)
1543         return;
1544
1545     if (!willRemoveNode)
1546         m_screenReader->clearFocus();
1547     else if (!m_screenReader->nodeWillBeRemoved(willRemoveNode))
1548         return;
1549
1550     send(Messages::WebPageProxy::DidScreenReaderFocusRectChanged(IntRect()));
1551 }
1552
1553 void WebPage::clearScreenReader()
1554 {
1555     m_screenReader.clear();
1556 }
1557 #endif
1558
1559 #if ENABLE(TIZEN_WEBKIT2_POPUP_INTERNAL)
1560 // FIXME: Currently with cached pages, hiding Popup list menu is not working correctly.
1561 // This patch is a fix allowing any popup list menu to get close for any page navigation.
1562 void WebPage::notifyTransitionToCommitted(bool forNewPage)
1563 {
1564     if (m_activePopupMenu) {
1565         TIZEN_LOGI("");
1566         m_activePopupMenu->hide();
1567     }
1568 }
1569 #endif
1570
1571 #if ENABLE(TIZEN_CSP)
1572 void WebPage::setContentSecurityPolicy(const String& policy, uint32_t headerType)
1573 {
1574     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1575     if (!frame)
1576         return;
1577
1578     Document* document = frame->document();
1579     if (!document)
1580         return;
1581
1582     document->contentSecurityPolicy()->didReceiveHeader(policy, static_cast<WebCore::ContentSecurityPolicy::HeaderType>(headerType));
1583 }
1584 #endif
1585
1586 #if ENABLE(TIZEN_INDEXED_DATABASE)
1587 void WebPage::setIndexedDatabaseDirectory(const String& path)
1588 {
1589     m_page->group().groupSettings()->setIndexedDBDatabasePath(path);
1590 }
1591 #endif
1592
1593 #if ENABLE(TIZEN_WEB_STORAGE)
1594 void WebPage::setLocalStorageDirectory(const String& path)
1595 {
1596     m_page->settings()->setLocalStorageDatabasePath(path);
1597 }
1598 #endif
1599 #endif // #if OS(TIZEN)
1600
1601 } // namespace WebKit