[EFL][DRT] Implement TextInputController.
[WebKit-https.git] / Source / WebKit / efl / WebCoreSupport / DumpRenderTreeSupportEfl.cpp
1 /*
2     Copyright (C) 2011 ProFUSION embedded systems
3     Copyright (C) 2011 Samsung Electronics
4
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Library General Public
7     License as published by the Free Software Foundation; either
8     version 2 of the License, or (at your option) any later version.
9
10     This library is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13     Library General Public License for more details.
14
15     You should have received a copy of the GNU Library General Public License
16     along with this library; see the file COPYING.LIB.  If not, write to
17     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18     Boston, MA 02110-1301, USA.
19 */
20
21 #include "config.h"
22 #include "DumpRenderTreeSupportEfl.h"
23
24 #include "FrameLoaderClientEfl.h"
25 #include "ewk_private.h"
26
27 #include <AnimationController.h>
28 #include <CSSComputedStyleDeclaration.h>
29 #include <DocumentLoader.h>
30 #include <EditorClientEfl.h>
31 #include <Eina.h>
32 #include <Evas.h>
33 #include <FindOptions.h>
34 #include <FloatSize.h>
35 #include <FocusController.h>
36 #include <FrameView.h>
37 #include <HTMLInputElement.h>
38 #include <InspectorController.h>
39 #include <IntRect.h>
40 #include <JSCSSStyleDeclaration.h>
41 #include <JSElement.h>
42 #include <PageGroup.h>
43 #include <PrintContext.h>
44 #include <RenderTreeAsText.h>
45 #include <Settings.h>
46 #include <TextIterator.h>
47 #include <WebKitMutationObserver.h>
48 #include <bindings/js/GCController.h>
49 #include <history/HistoryItem.h>
50 #include <workers/WorkerThread.h>
51
52 unsigned DumpRenderTreeSupportEfl::activeAnimationsCount(const Evas_Object* ewkFrame)
53 {
54     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
55
56     if (!frame)
57         return 0;
58
59     WebCore::AnimationController* animationController = frame->animation();
60
61     if (!animationController)
62         return 0;
63
64     return animationController->numberOfActiveAnimations(frame->document());
65 }
66
67 bool DumpRenderTreeSupportEfl::callShouldCloseOnWebView(Evas_Object* ewkFrame)
68 {
69     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
70
71     if (!frame)
72         return false;
73
74     return frame->loader()->shouldClose();
75 }
76
77 void DumpRenderTreeSupportEfl::clearFrameName(Evas_Object* ewkFrame)
78 {
79     if (WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame))
80         frame->tree()->clearName();
81 }
82
83 void DumpRenderTreeSupportEfl::clearOpener(Evas_Object* ewkFrame)
84 {
85     if (WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame))
86         frame->loader()->setOpener(0);
87 }
88
89 String DumpRenderTreeSupportEfl::counterValueByElementId(const Evas_Object* ewkFrame, const char* elementId)
90 {
91     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
92
93     if (!frame)
94         return String();
95
96     WebCore::Element* element = frame->document()->getElementById(elementId);
97
98     if (!element)
99         return String();
100
101     return WebCore::counterValueForElement(element);
102 }
103
104 bool DumpRenderTreeSupportEfl::elementDoesAutoCompleteForElementWithId(const Evas_Object* ewkFrame, const String& elementId)
105 {
106     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
107
108     if (!frame)
109         return false;
110
111     WebCore::Document* document = frame->document();
112     ASSERT(document);
113
114     WebCore::HTMLInputElement* inputElement = static_cast<WebCore::HTMLInputElement*>(document->getElementById(elementId));
115
116     if (!inputElement)
117         return false;
118
119     return inputElement->isTextField() && !inputElement->isPasswordField() && inputElement->shouldAutocomplete();
120 }
121
122 Eina_List* DumpRenderTreeSupportEfl::frameChildren(const Evas_Object* ewkFrame)
123 {
124     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
125
126     if (!frame)
127         return 0;
128
129     Eina_List* childFrames = 0;
130
131     for (unsigned index = 0; index < frame->tree()->childCount(); index++) {
132         WebCore::Frame *childFrame = frame->tree()->child(index);
133         WebCore::FrameLoaderClientEfl *client = static_cast<WebCore::FrameLoaderClientEfl*>(childFrame->loader()->client());
134
135         if (!client)
136             continue;
137
138         childFrames = eina_list_append(childFrames, client->webFrame());
139     }
140
141     return childFrames;
142 }
143
144 WebCore::Frame* DumpRenderTreeSupportEfl::frameParent(const Evas_Object* ewkFrame)
145 {
146     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
147
148     if (!frame)
149         return 0;
150
151     return frame->tree()->parent();
152 }
153
154 void DumpRenderTreeSupportEfl::layoutFrame(Evas_Object* ewkFrame)
155 {
156     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
157
158     if (!frame)
159         return;
160
161     WebCore::FrameView* frameView = frame->view();
162
163     if (!frameView)
164         return;
165
166     frameView->layout();
167 }
168
169 int DumpRenderTreeSupportEfl::numberOfPages(const Evas_Object* ewkFrame, float pageWidth, float pageHeight)
170 {
171     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
172
173     if (!frame)
174         return 0;
175
176     return WebCore::PrintContext::numberOfPages(frame, WebCore::FloatSize(pageWidth, pageHeight));
177 }
178
179 int DumpRenderTreeSupportEfl::numberOfPagesForElementId(const Evas_Object* ewkFrame, const char* elementId, float pageWidth, float pageHeight)
180 {
181     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
182
183     if (!frame)
184         return 0;
185
186     WebCore::Element *element = frame->document()->getElementById(elementId);
187
188     if (!element)
189         return 0;
190
191     return WebCore::PrintContext::pageNumberForElement(element, WebCore::FloatSize(pageWidth, pageHeight));
192 }
193
194 String DumpRenderTreeSupportEfl::pageSizeAndMarginsInPixels(const Evas_Object* ewkFrame, int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft)
195 {
196     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
197
198     if (!frame)
199         return String();
200
201     return WebCore::PrintContext::pageSizeAndMarginsInPixels(frame, pageNumber, width, height, marginTop, marginRight, marginBottom, marginLeft);
202 }
203
204 String DumpRenderTreeSupportEfl::pageProperty(const Evas_Object* ewkFrame, const char* propertyName, int pageNumber)
205 {
206     WebCore::Frame* coreFrame = EWKPrivate::coreFrame(ewkFrame);
207     if (!coreFrame)
208         return String();
209
210     return WebCore::PrintContext::pageProperty(coreFrame, propertyName, pageNumber);
211 }
212
213 bool DumpRenderTreeSupportEfl::pauseAnimation(Evas_Object* ewkFrame, const char* name, const char* elementId, double time)
214 {
215     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
216
217     if (!frame)
218         return false;
219
220     WebCore::Element* element = frame->document()->getElementById(elementId);
221
222     if (!element || !element->renderer())
223         return false;
224
225     return frame->animation()->pauseAnimationAtTime(element->renderer(), name, time);
226 }
227
228 bool DumpRenderTreeSupportEfl::pauseTransition(Evas_Object* ewkFrame, const char* name, const char* elementId, double time)
229 {
230     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
231
232     if (!frame)
233         return false;
234
235     WebCore::Element* element = frame->document()->getElementById(elementId);
236
237     if (!element || !element->renderer())
238         return false;
239
240     return frame->animation()->pauseTransitionAtTime(element->renderer(), name, time);
241 }
242
243 unsigned DumpRenderTreeSupportEfl::pendingUnloadEventCount(const Evas_Object* ewkFrame)
244 {
245     if (WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame))
246         return frame->domWindow()->pendingUnloadEventListeners();
247
248     return 0;
249 }
250
251 String DumpRenderTreeSupportEfl::renderTreeDump(Evas_Object* ewkFrame)
252 {
253     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
254
255     if (!frame)
256         return String();
257
258     WebCore::FrameView *frameView = frame->view();
259
260     if (frameView && frameView->layoutPending())
261         frameView->layout();
262
263     return WebCore::externalRepresentation(frame);
264 }
265
266 String DumpRenderTreeSupportEfl::responseMimeType(const Evas_Object* ewkFrame)
267 {
268     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
269
270     if (!frame)
271         return String();
272
273     WebCore::DocumentLoader *documentLoader = frame->loader()->documentLoader();
274
275     if (!documentLoader)
276         return String();
277
278     return documentLoader->responseMIMEType();
279 }
280
281 void DumpRenderTreeSupportEfl::resumeAnimations(Evas_Object* ewkFrame)
282 {
283     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
284
285     if (!frame)
286         return;
287
288     WebCore::AnimationController *animationController = frame->animation();
289     if (animationController)
290         animationController->resumeAnimations();
291 }
292
293 WebCore::IntRect DumpRenderTreeSupportEfl::selectionRectangle(const Evas_Object* ewkFrame)
294 {
295     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
296
297     if (!frame)
298         return WebCore::IntRect();
299
300     return enclosingIntRect(frame->selection()->bounds());
301 }
302
303 // Compare with "WebKit/Tools/DumpRenderTree/mac/FrameLoadDelegate.mm
304 String DumpRenderTreeSupportEfl::suitableDRTFrameName(const Evas_Object* ewkFrame)
305 {
306     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
307
308     if (!frame)
309         return String();
310
311     const String frameName(ewk_frame_name_get(ewkFrame));
312
313     if (ewkFrame == ewk_view_frame_main_get(ewk_frame_view_get(ewkFrame))) {
314         if (!frameName.isEmpty())
315             return String("main frame \"") + frameName + String("\"");
316
317         return String("main frame");
318     }
319
320     if (!frameName.isEmpty())
321         return String("frame \"") + frameName + String("\"");
322
323     return String("frame (anonymous)");
324 }
325
326 void DumpRenderTreeSupportEfl::suspendAnimations(Evas_Object* ewkFrame)
327 {
328     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
329
330     if (!frame)
331         return;
332
333     WebCore::AnimationController *animationController = frame->animation();
334     if (animationController)
335         animationController->suspendAnimations();
336 }
337
338 void DumpRenderTreeSupportEfl::setValueForUser(JSContextRef context, JSValueRef nodeObject, const String& value)
339 {
340     JSC::ExecState* exec = toJS(context);
341     WebCore::Element* element = WebCore::toElement(toJS(exec, nodeObject));
342     if (!element)
343         return;
344     WebCore::HTMLInputElement* inputElement = element->toInputElement();
345     if (!inputElement)
346         return;
347
348     inputElement->setValueForUser(value);
349 }
350
351 void DumpRenderTreeSupportEfl::setAutofilled(JSContextRef context, JSValueRef nodeObject, bool autofilled)
352 {
353     JSC::ExecState* exec = toJS(context);
354     WebCore::Element* element = WebCore::toElement(toJS(exec, nodeObject));
355     if (!element)
356         return;
357     WebCore::HTMLInputElement* inputElement = element->toInputElement();
358     if (!inputElement)
359         return;
360
361     inputElement->setAutofilled(autofilled);
362 }
363
364 void DumpRenderTreeSupportEfl::setDefersLoading(Evas_Object* ewkView, bool defers)
365 {
366     WebCore::Page* page = EWKPrivate::corePage(ewkView);
367
368     if (!page)
369         return;
370
371     page->setDefersLoading(defers);
372 }
373
374 void DumpRenderTreeSupportEfl::setLoadsSiteIconsIgnoringImageLoadingSetting(Evas_Object* ewkView, bool loadsSiteIconsIgnoringImageLoadingPreferences)
375 {
376     WebCore::Page* page = EWKPrivate::corePage(ewkView);
377     if (!page)
378         return;
379
380     page->settings()->setLoadsSiteIconsIgnoringImageLoadingSetting(loadsSiteIconsIgnoringImageLoadingPreferences);
381 }
382
383 void DumpRenderTreeSupportEfl::addUserStyleSheet(const Evas_Object* ewkView, const String& sourceCode, bool allFrames)
384 {
385     WebCore::Page* page = EWKPrivate::corePage(ewkView);
386     if (!page)
387         return;
388
389     page->group().addUserStyleSheetToWorld(WebCore::mainThreadNormalWorld(), sourceCode, WebCore::KURL(), nullptr, nullptr, allFrames ? WebCore::InjectInAllFrames : WebCore::InjectInTopFrameOnly);
390 }
391
392 void DumpRenderTreeSupportEfl::executeCoreCommandByName(const Evas_Object* ewkView, const char* name, const char* value)
393 {
394     WebCore::Page* page = EWKPrivate::corePage(ewkView);
395     if (!page)
396         return;
397
398     page->focusController()->focusedOrMainFrame()->editor()->command(name).execute(value);
399 }
400
401 bool DumpRenderTreeSupportEfl::findString(const Evas_Object* ewkView, const String& text, WebCore::FindOptions options)
402 {
403     WebCore::Page* page = EWKPrivate::corePage(ewkView);
404
405     if (!page)
406         return false;
407
408     return page->findString(text, options);
409 }
410
411 void DumpRenderTreeSupportEfl::setJavaScriptProfilingEnabled(const Evas_Object* ewkView, bool enabled)
412 {
413 #if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(INSPECTOR)
414     WebCore::Page* corePage = EWKPrivate::corePage(ewkView);
415     if (!corePage)
416         return;
417
418     WebCore::InspectorController* controller = corePage->inspectorController();
419     if (!controller)
420         return;
421
422     if (enabled)
423         controller->enableProfiler();
424     else
425         controller->disableProfiler();
426 #endif
427 }
428
429 bool DumpRenderTreeSupportEfl::isCommandEnabled(const Evas_Object* ewkView, const char* name)
430 {
431     WebCore::Page* page = EWKPrivate::corePage(ewkView);
432     if (!page)
433         return false;
434
435     return page->focusController()->focusedOrMainFrame()->editor()->command(name).isEnabled();
436 }
437
438 void DumpRenderTreeSupportEfl::setSmartInsertDeleteEnabled(Evas_Object* ewkView, bool enabled)
439 {
440     WebCore::Page* page = EWKPrivate::corePage(ewkView);
441     if (!page)
442         return;
443
444     WebCore::EditorClientEfl* editorClient = static_cast<WebCore::EditorClientEfl*>(page->editorClient());
445     if (!editorClient)
446         return;
447
448     editorClient->setSmartInsertDeleteEnabled(enabled);
449 }
450
451 void DumpRenderTreeSupportEfl::setSelectTrailingWhitespaceEnabled(Evas_Object* ewkView, bool enabled)
452 {
453     WebCore::Page* page = EWKPrivate::corePage(ewkView);
454     if (!page)
455         return;
456
457     WebCore::EditorClientEfl* editorClient = static_cast<WebCore::EditorClientEfl*>(page->editorClient());
458     if (!editorClient)
459         return;
460
461     editorClient->setSelectTrailingWhitespaceEnabled(enabled);
462 }
463
464 void DumpRenderTreeSupportEfl::garbageCollectorCollect()
465 {
466     WebCore::gcController().garbageCollectNow();
467 }
468
469 void DumpRenderTreeSupportEfl::garbageCollectorCollectOnAlternateThread(bool waitUntilDone)
470 {
471     WebCore::gcController().garbageCollectOnAlternateThreadForDebugging(waitUntilDone);
472 }
473
474 size_t DumpRenderTreeSupportEfl::javaScriptObjectsCount()
475 {
476     return WebCore::JSDOMWindow::commonJSGlobalData()->heap.objectCount();
477 }
478
479 unsigned DumpRenderTreeSupportEfl::workerThreadCount()
480 {
481 #if ENABLE(WORKERS)
482     return WebCore::WorkerThread::workerThreadCount();
483 #else
484     return 0;
485 #endif
486 }
487
488 HistoryItemChildrenVector DumpRenderTreeSupportEfl::childHistoryItems(const Ewk_History_Item* ewkHistoryItem)
489 {
490     WebCore::HistoryItem* historyItem = EWKPrivate::coreHistoryItem(ewkHistoryItem);
491     HistoryItemChildrenVector kids;
492
493     if (!historyItem)
494         return kids;
495
496     const WebCore::HistoryItemVector& children = historyItem->children();
497     const unsigned size = children.size();
498
499     for (unsigned i = 0; i < size; ++i) {
500         Ewk_History_Item* kid = ewk_history_item_new_from_core(children[i].get());
501         kids.append(kid);
502     }
503
504     return kids;
505 }
506
507 String DumpRenderTreeSupportEfl::historyItemTarget(const Ewk_History_Item* ewkHistoryItem)
508 {
509     WebCore::HistoryItem* historyItem = EWKPrivate::coreHistoryItem(ewkHistoryItem);
510
511     if (!historyItem)
512         return String();
513
514     return historyItem->target();
515 }
516
517 bool DumpRenderTreeSupportEfl::isTargetItem(const Ewk_History_Item* ewkHistoryItem)
518 {
519     WebCore::HistoryItem* historyItem = EWKPrivate::coreHistoryItem(ewkHistoryItem);
520
521     if (!historyItem)
522         return false;
523
524     return historyItem->isTargetItem();
525 }
526
527 void DumpRenderTreeSupportEfl::setMockScrollbarsEnabled(bool enable)
528 {
529     WebCore::Settings::setMockScrollbarsEnabled(enable);
530 }
531
532 void DumpRenderTreeSupportEfl::dumpConfigurationForViewport(Evas_Object* ewkView, int deviceDPI, const WebCore::IntSize& deviceSize, const WebCore::IntSize& availableSize)
533 {
534     WebCore::Page* page = EWKPrivate::corePage(ewkView);
535
536     if (!page)
537         return;
538     WebCore::ViewportArguments arguments = page->mainFrame()->document()->viewportArguments();
539     WebCore::ViewportAttributes attributes = computeViewportAttributes(arguments,
540             /* default layout width for non-mobile pages */ 980,
541             deviceSize.width(), deviceSize.height(),
542             deviceDPI,
543             availableSize);
544     restrictMinimumScaleFactorToViewportSize(attributes, availableSize);
545     restrictScaleFactorToInitialScaleIfNotUserScalable(attributes);
546     fprintf(stdout, "viewport size %dx%d scale %f with limits [%f, %f] and userScalable %f\n", static_cast<int>(attributes.layoutSize.width()), static_cast<int>(attributes.layoutSize.height()), attributes.initialScale, attributes.minimumScale, attributes.maximumScale, attributes.userScalable);
547 }
548
549 void DumpRenderTreeSupportEfl::deliverAllMutationsIfNecessary()
550 {
551 #if ENABLE(MUTATION_OBSERVERS)
552     WebCore::WebKitMutationObserver::deliverAllMutations();
553 #endif
554 }
555
556 void DumpRenderTreeSupportEfl::setEditingBehavior(Evas_Object* ewkView, const char* editingBehavior)
557 {
558     WebCore::EditingBehaviorType coreEditingBehavior;
559
560     if (!strcmp(editingBehavior, "win"))
561         coreEditingBehavior = WebCore::EditingWindowsBehavior;
562     else if (!strcmp(editingBehavior, "mac"))
563         coreEditingBehavior = WebCore::EditingMacBehavior;
564     else if (!strcmp(editingBehavior, "unix"))
565         coreEditingBehavior = WebCore::EditingUnixBehavior;
566     else {
567         ASSERT_NOT_REACHED();
568         return;
569     }
570
571     WebCore::Page* corePage = EWKPrivate::corePage(ewkView);
572     if (!corePage)
573         return;
574
575     corePage->settings()->setEditingBehaviorType(coreEditingBehavior);
576 }
577
578 String DumpRenderTreeSupportEfl::markerTextForListItem(JSContextRef context, JSValueRef nodeObject)
579 {
580     JSC::ExecState* exec = toJS(context);
581     WebCore::Element* element = WebCore::toElement(toJS(exec, nodeObject));
582     if (!element)
583         return String();
584
585     return WebCore::markerTextForListItem(element);
586 }
587
588 void DumpRenderTreeSupportEfl::setInteractiveFormValidationEnabled(Evas_Object* ewkView, bool enabled)
589 {
590     WebCore::Page* corePage = EWKPrivate::corePage(ewkView);
591     if (corePage)
592         corePage->settings()->setInteractiveFormValidationEnabled(enabled);
593 }
594
595 JSValueRef DumpRenderTreeSupportEfl::computedStyleIncludingVisitedInfo(JSContextRef context, JSValueRef value)
596 {
597     if (!value)
598         return JSValueMakeUndefined(context);
599
600     JSC::ExecState* exec = toJS(context);
601     JSC::JSValue jsValue = toJS(exec, value);
602     if (!jsValue.inherits(&WebCore::JSElement::s_info))
603         return JSValueMakeUndefined(context);
604
605     WebCore::JSElement* jsElement = static_cast<WebCore::JSElement*>(asObject(jsValue));
606     WebCore::Element* element = jsElement->impl();
607     RefPtr<WebCore::CSSComputedStyleDeclaration> style = WebCore::CSSComputedStyleDeclaration::create(element, true);
608     return toRef(exec, toJS(exec, jsElement->globalObject(), style.get()));
609 }
610
611 void DumpRenderTreeSupportEfl::setAuthorAndUserStylesEnabled(Evas_Object* ewkView, bool enabled)
612 {
613     WebCore::Page* corePage = EWKPrivate::corePage(ewkView);
614     if (!corePage)
615         return;
616
617     corePage->settings()->setAuthorAndUserStylesEnabled(enabled);
618 }
619
620 void DumpRenderTreeSupportEfl::setComposition(Evas_Object* ewkView, const char* text, int start, int length)
621 {
622     WebCore::Page* page = EWKPrivate::corePage(ewkView);
623     if (!page || !page->focusController() || !page->focusController()->focusedOrMainFrame())
624         return;
625
626     WebCore::Editor* editor = page->focusController()->focusedOrMainFrame()->editor();
627     if (!editor || (!editor->canEdit() && !editor->hasComposition()))
628         return;
629
630     const String compositionString = String::fromUTF8(text);
631     Vector<WebCore::CompositionUnderline> underlines;
632     underlines.append(WebCore::CompositionUnderline(0, compositionString.length(), WebCore::Color(0, 0, 0), false));
633     editor->setComposition(compositionString, underlines, start, start + length);
634 }
635
636 bool DumpRenderTreeSupportEfl::hasComposition(const Evas_Object* ewkView)
637 {
638     const WebCore::Page* page = EWKPrivate::corePage(ewkView);
639     if (!page || !page->focusController() || !page->focusController()->focusedOrMainFrame())
640         return false;
641
642     const WebCore::Editor* editor = page->focusController()->focusedOrMainFrame()->editor();
643     if (!editor)
644         return false;
645
646     return editor->hasComposition();
647 }
648
649 bool DumpRenderTreeSupportEfl::compositionRange(Evas_Object* ewkView, int* start, int* length)
650 {
651     *start = *length = 0;
652
653     WebCore::Page* page = EWKPrivate::corePage(ewkView);
654     if (!page || !page->focusController() || !page->focusController()->focusedOrMainFrame())
655         return false;
656
657     WebCore::Editor* editor = page->focusController()->focusedOrMainFrame()->editor();
658     if (!editor || !editor->hasComposition())
659         return false;
660
661     *start = editor->compositionStart();
662     *length = editor->compositionEnd() - *start;
663     return true;
664 }
665
666 void DumpRenderTreeSupportEfl::confirmComposition(Evas_Object* ewkView, const char* text)
667 {
668     WebCore::Page* page = EWKPrivate::corePage(ewkView);
669     if (!page || !page->focusController() || !page->focusController()->focusedOrMainFrame())
670         return;
671
672     WebCore::Editor* editor = page->focusController()->focusedOrMainFrame()->editor();
673     if (!editor)
674         return;
675
676     if (!editor->hasComposition()) {
677         editor->insertText(String::fromUTF8(text), 0);
678         return;
679     }
680
681     if (text) {
682         editor->confirmComposition(String::fromUTF8(text));
683         return;
684     }
685     editor->confirmComposition();
686 }
687
688 WebCore::IntRect DumpRenderTreeSupportEfl::firstRectForCharacterRange(Evas_Object* ewkView, int location, int length)
689 {
690     WebCore::Page* page = EWKPrivate::corePage(ewkView);
691     if (!page || !page->focusController() || !page->focusController()->focusedOrMainFrame() || !page->focusController()->focusedOrMainFrame()->editor())
692         return WebCore::IntRect();
693
694     if ((location + length < location) && (location + length))
695         length = 0;
696
697     WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
698     WebCore::Editor* editor = frame->editor();
699
700     RefPtr<WebCore::Range> range = WebCore::TextIterator::rangeFromLocationAndLength(frame->selection()->rootEditableElementOrDocumentElement(), location, length);
701     if (!range)
702         return WebCore::IntRect();
703
704     return editor->firstRectForRange(range.get());
705 }
706
707 bool DumpRenderTreeSupportEfl::selectedRange(Evas_Object* ewkView, int* start, int* length)
708 {
709     if (!(start && length))
710         return false;
711
712     WebCore::Page* page = EWKPrivate::corePage(ewkView);
713     if (!page || !page->focusController() || !page->focusController()->focusedOrMainFrame())
714         return false;
715
716     WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
717     RefPtr<WebCore::Range> range = frame->selection()->toNormalizedRange().get();
718     if (!range)
719         return false;
720
721     WebCore::Element* selectionRoot = frame->selection()->rootEditableElement();
722     WebCore::Element* scope = selectionRoot ? selectionRoot : frame->document()->documentElement();
723
724     RefPtr<WebCore::Range> testRange = WebCore::Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset());
725     *start = WebCore::TextIterator::rangeLength(testRange.get());
726
727     WebCore::ExceptionCode ec;
728     testRange->setEnd(range->endContainer(), range->endOffset(), ec);
729     *length = WebCore::TextIterator::rangeLength(testRange.get());
730
731     return true;
732 }