c442c1bf9630c8726ecb1feeb3e8917d2b46b750
[WebKit-https.git] / Source / WebKit / efl / WebCoreSupport / DumpRenderTreeSupportEfl.cpp
1 /*
2     Copyright (C) 2011 ProFUSION embedded systems
3     Copyright (C) 2011 Samsung Electronics
4     Copyright (C) 2012 Intel Corporation. All rights reserved.
5     Copyright (C) 2013 Apple Inc. All rights reserved.
6
7     This library is free software; you can redistribute it and/or
8     modify it under the terms of the GNU Library General Public
9     License as published by the Free Software Foundation; either
10     version 2 of the License, or (at your option) any later version.
11
12     This library is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15     Library General Public License for more details.
16
17     You should have received a copy of the GNU Library General Public License
18     along with this library; see the file COPYING.LIB.  If not, write to
19     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20     Boston, MA 02110-1301, USA.
21 */
22
23 #include "config.h"
24 #include "DumpRenderTreeSupportEfl.h"
25
26 #include "FrameLoaderClientEfl.h"
27 #include "ewk_frame_private.h"
28 #include "ewk_history_private.h"
29 #include "ewk_private.h"
30 #include "ewk_view_private.h"
31
32 #include <APICast.h>
33 #include <AnimationController.h>
34 #include <DOMWindow.h>
35 #include <DocumentLoader.h>
36 #include <Editor.h>
37 #include <EditorClientEfl.h>
38 #include <Eina.h>
39 #include <Evas.h>
40 #include <FindOptions.h>
41 #include <FloatSize.h>
42 #include <FocusController.h>
43 #include <FrameLoader.h>
44 #include <FrameSelection.h>
45 #include <FrameView.h>
46 #include <HTMLInputElement.h>
47 #include <InspectorController.h>
48 #include <IntRect.h>
49 #include <JSCSSStyleDeclaration.h>
50 #include <JSDOMWindow.h>
51 #include <JSElement.h>
52 #include <JavaScriptCore/OpaqueJSString.h>
53 #include <MemoryCache.h>
54 #include <MutationObserver.h>
55 #include <PageGroup.h>
56 #include <PrintContext.h>
57 #include <RenderTreeAsText.h>
58 #include <ResourceLoadScheduler.h>
59 #include <RuntimeEnabledFeatures.h>
60 #include <SchemeRegistry.h>
61 #include <ScriptController.h>
62 #include <ScriptValue.h>
63 #include <Settings.h>
64 #include <TextIterator.h>
65 #include <bindings/js/GCController.h>
66 #include <history/HistoryItem.h>
67 #include <wtf/HashMap.h>
68
69 #if ENABLE(GEOLOCATION)
70 #include <GeolocationClientMock.h>
71 #include <GeolocationController.h>
72 #include <GeolocationError.h>
73 #include <GeolocationPosition.h>
74 #include <wtf/CurrentTime.h>
75 #endif
76
77 #if HAVE(ACCESSIBILITY)
78 #include "AXObjectCache.h"
79 #include "AccessibilityObject.h"
80 #include "WebKitAccessibleWrapperAtk.h"
81 #endif
82
83 #define DRT_SUPPORT_FRAME_GET_OR_RETURN(ewkFrame, frame, ...) \
84     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);  \
85     if (!frame)                                               \
86         return __VA_ARGS__;
87
88 #define DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page, ...) \
89     WebCore::Page* page = EWKPrivate::corePage(ewkView);  \
90     if (!page)                                            \
91         return __VA_ARGS__;
92
93 bool DumpRenderTreeSupportEfl::s_drtRun = false;
94
95 void DumpRenderTreeSupportEfl::setDumpRenderTreeModeEnabled(bool enabled)
96 {
97     s_drtRun = enabled;
98 }
99
100 bool DumpRenderTreeSupportEfl::dumpRenderTreeModeEnabled()
101 {
102     return s_drtRun;
103 }
104
105 bool DumpRenderTreeSupportEfl::callShouldCloseOnWebView(Evas_Object* ewkFrame)
106 {
107     DRT_SUPPORT_FRAME_GET_OR_RETURN(ewkFrame, frame, false);
108
109     return frame->loader().shouldClose();
110 }
111
112 void DumpRenderTreeSupportEfl::clearFrameName(Evas_Object* ewkFrame)
113 {
114     DRT_SUPPORT_FRAME_GET_OR_RETURN(ewkFrame, frame);
115
116     frame->tree().clearName();
117 }
118
119 void DumpRenderTreeSupportEfl::clearOpener(Evas_Object* ewkFrame)
120 {
121     DRT_SUPPORT_FRAME_GET_OR_RETURN(ewkFrame, frame);
122
123     frame->loader().setOpener(0);
124 }
125
126 String DumpRenderTreeSupportEfl::layerTreeAsText(const Evas_Object* ewkFrame)
127 {
128     DRT_SUPPORT_FRAME_GET_OR_RETURN(ewkFrame, frame, String());
129
130     return frame->layerTreeAsText();
131 }
132
133 Eina_List* DumpRenderTreeSupportEfl::frameChildren(const Evas_Object* ewkFrame)
134 {
135     DRT_SUPPORT_FRAME_GET_OR_RETURN(ewkFrame, frame, 0);
136
137     Eina_List* childFrames = 0;
138
139     for (unsigned index = 0; index < frame->tree().childCount(); index++) {
140         WebCore::Frame *childFrame = frame->tree().child(index);
141         WebCore::FrameLoaderClientEfl& client = static_cast<WebCore::FrameLoaderClientEfl&>(childFrame->loader().client());
142
143         childFrames = eina_list_append(childFrames, client.webFrame());
144     }
145
146     return childFrames;
147 }
148
149 WebCore::Frame* DumpRenderTreeSupportEfl::frameParent(const Evas_Object* ewkFrame)
150 {
151     DRT_SUPPORT_FRAME_GET_OR_RETURN(ewkFrame, frame, 0);
152
153     return frame->tree().parent();
154 }
155
156 void DumpRenderTreeSupportEfl::layoutFrame(Evas_Object* ewkFrame)
157 {
158     DRT_SUPPORT_FRAME_GET_OR_RETURN(ewkFrame, frame);
159
160     if (!frame->view())
161         return;
162
163     frame->view()->layout();
164 }
165
166 unsigned DumpRenderTreeSupportEfl::pendingUnloadEventCount(const Evas_Object* ewkFrame)
167 {
168     DRT_SUPPORT_FRAME_GET_OR_RETURN(ewkFrame, frame, 0);
169
170     return frame->document()->domWindow()->pendingUnloadEventListeners();
171 }
172
173 String DumpRenderTreeSupportEfl::renderTreeDump(Evas_Object* ewkFrame)
174 {
175     DRT_SUPPORT_FRAME_GET_OR_RETURN(ewkFrame, frame, String());
176
177     WebCore::FrameView *frameView = frame->view();
178
179     if (frameView && frameView->layoutPending())
180         frameView->layout();
181
182     return WebCore::externalRepresentation(frame);
183 }
184
185 String DumpRenderTreeSupportEfl::responseMimeType(const Evas_Object* ewkFrame)
186 {
187     DRT_SUPPORT_FRAME_GET_OR_RETURN(ewkFrame, frame, String());
188
189     WebCore::DocumentLoader *documentLoader = frame->loader().documentLoader();
190
191     if (!documentLoader)
192         return String();
193
194     return documentLoader->responseMIMEType();
195 }
196
197 WebCore::IntRect DumpRenderTreeSupportEfl::selectionRectangle(const Evas_Object* ewkFrame)
198 {
199     DRT_SUPPORT_FRAME_GET_OR_RETURN(ewkFrame, frame, WebCore::IntRect());
200
201     return enclosingIntRect(frame->selection().bounds());
202 }
203
204 // Compare with "WebKit/Tools/DumpRenderTree/mac/FrameLoadDelegate.mm
205 String DumpRenderTreeSupportEfl::suitableDRTFrameName(const Evas_Object* ewkFrame)
206 {
207     DRT_SUPPORT_FRAME_GET_OR_RETURN(ewkFrame, frame, String());
208
209     const String frameName(ewk_frame_name_get(ewkFrame));
210
211     if (ewkFrame == ewk_view_frame_main_get(ewk_frame_view_get(ewkFrame))) {
212         if (!frameName.isEmpty())
213             return String("main frame \"") + frameName + String("\"");
214
215         return String("main frame");
216     }
217
218     if (!frameName.isEmpty())
219         return String("frame \"") + frameName + String("\"");
220
221     return String("frame (anonymous)");
222 }
223
224 const WebCore::URL DumpRenderTreeSupportEfl::provisionalURL(const Evas_Object* ewkFrame)
225 {
226     DRT_SUPPORT_FRAME_GET_OR_RETURN(ewkFrame, frame, WebCore::URL());
227
228     WebCore::DocumentLoader* provisionalDocumentLoader = frame->loader().provisionalDocumentLoader();
229     if (!provisionalDocumentLoader)
230         return WebCore::URL();
231
232     return provisionalDocumentLoader->url();
233 }
234
235 void DumpRenderTreeSupportEfl::setValueForUser(JSContextRef context, JSValueRef nodeObject, const String& value)
236 {
237     JSC::ExecState* exec = toJS(context);
238     WebCore::Element* element = WebCore::toElement(toJS(exec, nodeObject));
239     if (!element)
240         return;
241     WebCore::HTMLInputElement* inputElement = element->toInputElement();
242     if (!inputElement)
243         return;
244
245     inputElement->setValueForUser(value);
246 }
247
248 void DumpRenderTreeSupportEfl::setDefersLoading(Evas_Object* ewkView, bool defers)
249 {
250     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page);
251
252     page->setDefersLoading(defers);
253 }
254
255 void DumpRenderTreeSupportEfl::setLoadsSiteIconsIgnoringImageLoadingSetting(Evas_Object* ewkView, bool loadsSiteIconsIgnoringImageLoadingPreferences)
256 {
257     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page);
258
259     page->settings().setLoadsSiteIconsIgnoringImageLoadingSetting(loadsSiteIconsIgnoringImageLoadingPreferences);
260 }
261
262 void DumpRenderTreeSupportEfl::setMinimumLogicalFontSize(Evas_Object* ewkView, int size)
263 {
264     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page);
265
266     page->settings().setMinimumLogicalFontSize(size);
267 }
268
269 void DumpRenderTreeSupportEfl::addUserScript(const Evas_Object* ewkView, const String& sourceCode, bool runAtStart, bool allFrames)
270 {
271     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page);
272
273     page->group().addUserScriptToWorld(WebCore::mainThreadNormalWorld(), sourceCode, WebCore::URL(),
274                                        Vector<String>(), Vector<String>(), runAtStart ? WebCore::InjectAtDocumentStart : WebCore::InjectAtDocumentEnd,
275                                        allFrames ? WebCore::InjectInAllFrames : WebCore::InjectInTopFrameOnly);
276 }
277
278 void DumpRenderTreeSupportEfl::clearUserScripts(const Evas_Object* ewkView)
279 {
280     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page);
281
282     page->group().removeUserScriptsFromWorld(WebCore::mainThreadNormalWorld());
283 }
284
285 void DumpRenderTreeSupportEfl::addUserStyleSheet(const Evas_Object* ewkView, const String& sourceCode, bool allFrames)
286 {
287     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page);
288
289     page->group().addUserStyleSheetToWorld(WebCore::mainThreadNormalWorld(), sourceCode, WebCore::URL(), Vector<String>(), Vector<String>(), allFrames ? WebCore::InjectInAllFrames : WebCore::InjectInTopFrameOnly);
290 }
291
292 void DumpRenderTreeSupportEfl::clearUserStyleSheets(const Evas_Object* ewkView)
293 {
294     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page);
295
296     page->group().removeUserStyleSheetsFromWorld(WebCore::mainThreadNormalWorld());
297 }
298
299 void DumpRenderTreeSupportEfl::executeCoreCommandByName(const Evas_Object* ewkView, const char* name, const char* value)
300 {
301     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page);
302
303     page->focusController().focusedOrMainFrame().editor().command(name).execute(value);
304 }
305
306 bool DumpRenderTreeSupportEfl::findString(const Evas_Object* ewkView, const String& text, WebCore::FindOptions options)
307 {
308     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page, false);
309
310     return page->findString(text, options);
311 }
312
313 void DumpRenderTreeSupportEfl::setCSSGridLayoutEnabled(const Evas_Object* ewkView, bool enabled)
314 {
315     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page);
316
317     page->settings().setCSSGridLayoutEnabled(enabled);
318 }
319
320 void DumpRenderTreeSupportEfl::setCSSRegionsEnabled(const Evas_Object* ewkView, bool enabled)
321 {
322     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page);
323
324     WebCore::RuntimeEnabledFeatures::sharedFeatures().setCSSRegionsEnabled(enabled);
325 }
326
327 void DumpRenderTreeSupportEfl::setSeamlessIFramesEnabled(bool enabled)
328 {
329 #if ENABLE(IFRAME_SEAMLESS)
330     WebCore::RuntimeEnabledFeatures::sharedFeatures().setSeamlessIFramesEnabled(enabled);
331 #else
332     UNUSED_PARAM(enabled);
333 #endif
334 }
335
336 void DumpRenderTreeSupportEfl::setWebAudioEnabled(Evas_Object* ewkView, bool enabled)
337 {
338 #if ENABLE(WEB_AUDIO)
339     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page);
340
341     page->settings().setWebAudioEnabled(enabled);
342 #else
343     UNUSED_PARAM(ewkView);
344     UNUSED_PARAM(enabled);
345 #endif
346 }
347
348 bool DumpRenderTreeSupportEfl::isCommandEnabled(const Evas_Object* ewkView, const char* name)
349 {
350     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page, false);
351
352     return page->focusController().focusedOrMainFrame().editor().command(name).isEnabled();
353 }
354
355 void DumpRenderTreeSupportEfl::forceLayout(Evas_Object* ewkFrame)
356 {
357     ewk_frame_force_layout(ewkFrame);
358 }
359
360 void DumpRenderTreeSupportEfl::setTracksRepaints(Evas_Object* ewkFrame, bool enabled)
361 {
362     DRT_SUPPORT_FRAME_GET_OR_RETURN(ewkFrame, frame);
363
364     if (frame->view())
365         frame->view()->setTracksRepaints(enabled);
366 }
367
368 void DumpRenderTreeSupportEfl::resetTrackedRepaints(Evas_Object* ewkFrame)
369 {
370     DRT_SUPPORT_FRAME_GET_OR_RETURN(ewkFrame, frame);
371
372     if (frame->view())
373         frame->view()->resetTrackedRepaints();
374 }
375
376 bool DumpRenderTreeSupportEfl::isTrackingRepaints(const Evas_Object* ewkFrame)
377 {
378     DRT_SUPPORT_FRAME_GET_OR_RETURN(ewkFrame, frame, false);
379
380     if (!frame->view())
381         return false;
382
383     return frame->view()->isTrackingRepaints();
384 }
385
386 Eina_List* DumpRenderTreeSupportEfl::trackedRepaintRects(const Evas_Object* ewkFrame)
387 {
388     DRT_SUPPORT_FRAME_GET_OR_RETURN(ewkFrame, frame, 0);
389
390     if (!frame->view())
391         return 0;
392
393     const Vector<WebCore::IntRect>& repaintRects = frame->view()->trackedRepaintRects();
394     size_t count = repaintRects.size();
395     Eina_List* rectList = 0;
396
397     for (size_t i = 0; i < count; ++i) {
398         Eina_Rectangle* rect = eina_rectangle_new(repaintRects[i].x(), repaintRects[i].y(), repaintRects[i].width(), repaintRects[i].height());
399         rectList = eina_list_append(rectList, rect);
400     }
401
402     return rectList;
403 }
404
405 void DumpRenderTreeSupportEfl::garbageCollectorCollect()
406 {
407     WebCore::gcController().garbageCollectNow();
408 }
409
410 void DumpRenderTreeSupportEfl::garbageCollectorCollectOnAlternateThread(bool waitUntilDone)
411 {
412     WebCore::gcController().garbageCollectOnAlternateThreadForDebugging(waitUntilDone);
413 }
414
415 size_t DumpRenderTreeSupportEfl::javaScriptObjectsCount()
416 {
417     return WebCore::JSDOMWindow::commonVM()->heap.objectCount();
418 }
419
420 void DumpRenderTreeSupportEfl::setDeadDecodedDataDeletionInterval(double interval)
421 {
422     WebCore::memoryCache()->setDeadDecodedDataDeletionInterval(interval);
423 }
424
425 HistoryItemChildrenVector DumpRenderTreeSupportEfl::childHistoryItems(const Ewk_History_Item* ewkHistoryItem)
426 {
427     WebCore::HistoryItem* historyItem = EWKPrivate::coreHistoryItem(ewkHistoryItem);
428     HistoryItemChildrenVector kids;
429
430     if (!historyItem)
431         return kids;
432
433     const WebCore::HistoryItemVector& children = historyItem->children();
434     const unsigned size = children.size();
435
436     for (unsigned i = 0; i < size; ++i) {
437         Ewk_History_Item* kid = ewk_history_item_new_from_core(children[i].get());
438         kids.append(kid);
439     }
440
441     return kids;
442 }
443
444 String DumpRenderTreeSupportEfl::historyItemTarget(const Ewk_History_Item* ewkHistoryItem)
445 {
446     WebCore::HistoryItem* historyItem = EWKPrivate::coreHistoryItem(ewkHistoryItem);
447
448     if (!historyItem)
449         return String();
450
451     return historyItem->target();
452 }
453
454 bool DumpRenderTreeSupportEfl::isTargetItem(const Ewk_History_Item* ewkHistoryItem)
455 {
456     WebCore::HistoryItem* historyItem = EWKPrivate::coreHistoryItem(ewkHistoryItem);
457
458     if (!historyItem)
459         return false;
460
461     return historyItem->isTargetItem();
462 }
463
464 void DumpRenderTreeSupportEfl::evaluateInWebInspector(const Evas_Object* ewkView, long callId, const String& script)
465 {
466 #if ENABLE(INSPECTOR)
467     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page);
468
469     if (page->inspectorController())
470         page->inspectorController()->evaluateForTestInFrontend(callId, script);
471 #else
472     UNUSED_PARAM(ewkView);
473     UNUSED_PARAM(callId);
474     UNUSED_PARAM(script);
475 #endif
476 }
477
478 void DumpRenderTreeSupportEfl::evaluateScriptInIsolatedWorld(const Evas_Object* ewkFrame, int worldID, JSObjectRef globalObject, const String& script)
479 {
480     DRT_SUPPORT_FRAME_GET_OR_RETURN(ewkFrame, frame);
481
482     // Comment from mac: Start off with some guess at a frame and a global object, we'll try to do better...!
483     WebCore::JSDOMWindow* anyWorldGlobalObject = frame->script().globalObject(WebCore::mainThreadNormalWorld());
484
485     // Comment from mac: The global object is probably a shell object? - if so, we know how to use this!
486     JSC::JSObject* globalObjectObj = toJS(globalObject);
487     if (!strcmp(globalObjectObj->classInfo()->className, "JSDOMWindowShell"))
488         anyWorldGlobalObject = static_cast<WebCore::JSDOMWindowShell*>(globalObjectObj)->window();
489
490     // Comment from mac: Get the frame from the global object we've settled on.
491     WebCore::Frame* globalFrame = anyWorldGlobalObject->impl()->frame();
492     if (!globalFrame)
493         return;
494
495     WebCore::ScriptController& proxy = globalFrame->script();
496
497     static WTF::HashMap<int, WTF::RefPtr<WebCore::DOMWrapperWorld > > worldMap;
498
499     WTF::RefPtr<WebCore::DOMWrapperWorld> scriptWorld;
500     if (!worldID)
501         scriptWorld = WebCore::ScriptController::createWorld();
502     else {
503         WTF::HashMap<int, RefPtr<WebCore::DOMWrapperWorld > >::const_iterator it = worldMap.find(worldID);
504         if (it != worldMap.end())
505             scriptWorld = (*it).value;
506         else {
507             scriptWorld = WebCore::ScriptController::createWorld();
508             worldMap.set(worldID, scriptWorld);
509         }
510     }
511
512     // The code below is only valid for JSC, V8 specific code is to be added
513     // when V8 will be supported in EFL port. See Qt implemenation.
514     proxy.executeScriptInWorld(*scriptWorld, script, true);
515 }
516
517 JSGlobalContextRef DumpRenderTreeSupportEfl::globalContextRefForFrame(const Evas_Object* ewkFrame)
518 {
519     DRT_SUPPORT_FRAME_GET_OR_RETURN(ewkFrame, frame, 0);
520
521     return toGlobalRef(frame->script().globalObject(WebCore::mainThreadNormalWorld())->globalExec());
522 }
523
524 void DumpRenderTreeSupportEfl::setMockScrollbarsEnabled(bool enable)
525 {
526     WebCore::Settings::setMockScrollbarsEnabled(enable);
527 }
528
529 void DumpRenderTreeSupportEfl::deliverAllMutationsIfNecessary()
530 {
531     WebCore::MutationObserver::deliverAllMutations();
532 }
533
534 void DumpRenderTreeSupportEfl::setInteractiveFormValidationEnabled(Evas_Object* ewkView, bool enabled)
535 {
536     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page);
537
538     page->settings().setInteractiveFormValidationEnabled(enabled);
539 }
540
541 void DumpRenderTreeSupportEfl::setValidationMessageTimerMagnification(Evas_Object* ewkView, int value)
542 {
543     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page);
544
545     page->settings().setValidationMessageTimerMagnification(value);
546 }
547
548 void DumpRenderTreeSupportEfl::setAuthorAndUserStylesEnabled(Evas_Object* ewkView, bool enabled)
549 {
550     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page);
551
552     page->settings().setAuthorAndUserStylesEnabled(enabled);
553 }
554
555 void DumpRenderTreeSupportEfl::setSerializeHTTPLoads(bool enabled)
556 {
557     WebCore::resourceLoadScheduler()->setSerialLoadingEnabled(enabled);
558 }
559
560 void DumpRenderTreeSupportEfl::setShouldTrackVisitedLinks(bool shouldTrack)
561 {
562     WebCore::PageGroup::setShouldTrackVisitedLinks(shouldTrack);
563 }
564
565 void DumpRenderTreeSupportEfl::setComposition(Evas_Object* ewkView, const char* text, int start, int length)
566 {
567     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page);
568
569     WebCore::Editor& editor = page->focusController().focusedOrMainFrame().editor();
570     if (!editor.canEdit() && !editor.hasComposition())
571         return;
572
573     const String compositionString = String::fromUTF8(text);
574     Vector<WebCore::CompositionUnderline> underlines;
575     underlines.append(WebCore::CompositionUnderline(0, compositionString.length(), WebCore::Color(0, 0, 0), false));
576     editor.setComposition(compositionString, underlines, start, start + length);
577 }
578
579 bool DumpRenderTreeSupportEfl::hasComposition(const Evas_Object* ewkView)
580 {
581     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page, false);
582
583     return page->focusController().focusedOrMainFrame().editor().hasComposition();
584 }
585
586 bool DumpRenderTreeSupportEfl::compositionRange(Evas_Object* ewkView, int* start, int* length)
587 {
588     *start = *length = 0;
589
590     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page, false);
591
592     WebCore::Editor& editor = page->focusController().focusedOrMainFrame().editor();
593     if (!editor.hasComposition())
594         return false;
595
596     *start = editor.compositionStart();
597     *length = editor.compositionEnd() - *start;
598     return true;
599 }
600
601 void DumpRenderTreeSupportEfl::confirmComposition(Evas_Object* ewkView, const char* text)
602 {
603     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page);
604
605     WebCore::Editor& editor = page->focusController().focusedOrMainFrame().editor();
606
607     if (!editor.hasComposition()) {
608         editor.insertText(String::fromUTF8(text), 0);
609         return;
610     }
611
612     if (text) {
613         editor.confirmComposition(String::fromUTF8(text));
614         return;
615     }
616     editor.confirmComposition();
617 }
618
619 WebCore::IntRect DumpRenderTreeSupportEfl::firstRectForCharacterRange(Evas_Object* ewkView, int location, int length)
620 {
621     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page, WebCore::IntRect());
622
623     if ((location + length < location) && (location + length))
624         length = 0;
625
626     WebCore::Frame& frame = page->focusController().focusedOrMainFrame();
627
628     RefPtr<WebCore::Range> range = WebCore::TextIterator::rangeFromLocationAndLength(frame.selection().rootEditableElementOrDocumentElement(), location, length);
629     if (!range)
630         return WebCore::IntRect();
631
632     return frame.editor().firstRectForRange(range.get());
633 }
634
635 bool DumpRenderTreeSupportEfl::selectedRange(Evas_Object* ewkView, int* start, int* length)
636 {
637     if (!(start && length))
638         return false;
639
640     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page, false);
641
642     WebCore::Frame& frame = page->focusController().focusedOrMainFrame();
643     RefPtr<WebCore::Range> range = frame.selection().toNormalizedRange().get();
644     if (!range)
645         return false;
646
647     WebCore::Element* selectionRoot = frame.selection().rootEditableElement();
648     WebCore::Element* scope = selectionRoot ? selectionRoot : frame.document()->documentElement();
649
650     RefPtr<WebCore::Range> testRange = WebCore::Range::create(&scope->document(), scope, 0, range->startContainer(), range->startOffset());
651     *start = WebCore::TextIterator::rangeLength(testRange.get());
652
653     WebCore::ExceptionCode ec;
654     testRange->setEnd(range->endContainer(), range->endOffset(), ec);
655     *length = WebCore::TextIterator::rangeLength(testRange.get());
656
657     return true;
658 }
659
660 void DumpRenderTreeSupportEfl::setDomainRelaxationForbiddenForURLScheme(bool forbidden, const String& scheme)
661 {
662     WebCore::SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(forbidden, scheme);
663 }
664
665 void DumpRenderTreeSupportEfl::resetGeolocationClientMock(const Evas_Object* ewkView)
666 {
667 #if ENABLE(GEOLOCATION)
668     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page);
669
670     WebCore::GeolocationClientMock* mock = static_cast<WebCore::GeolocationClientMock*>(WebCore::GeolocationController::from(page)->client());
671     mock->reset();
672 #else
673     UNUSED_PARAM(ewkView);
674 #endif
675 }
676
677 void DumpRenderTreeSupportEfl::setMockGeolocationPermission(const Evas_Object* ewkView, bool allowed)
678 {
679 #if ENABLE(GEOLOCATION)
680     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page);
681
682     WebCore::GeolocationClientMock* mock = static_cast<WebCore::GeolocationClientMock*>(WebCore::GeolocationController::from(page)->client());
683     mock->setPermission(allowed);
684 #else
685     UNUSED_PARAM(ewkView);
686     UNUSED_PARAM(allowed);
687 #endif
688 }
689
690 void DumpRenderTreeSupportEfl::setMockGeolocationPosition(const Evas_Object* ewkView, double latitude, double longitude, double accuracy, bool canProvideAltitude, double altitude, bool canProvideAltitudeAccuracy, double altitudeAccuracy, bool canProvideHeading, double heading, bool canProvideSpeed, double speed)
691 {
692 #if ENABLE(GEOLOCATION)
693     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page);
694
695     WebCore::GeolocationClientMock* mock = static_cast<WebCore::GeolocationClientMock*>(WebCore::GeolocationController::from(page)->client());
696     mock->setPosition(WebCore::GeolocationPosition::create(currentTime(), latitude, longitude, accuracy, canProvideAltitude, altitude, canProvideAltitudeAccuracy, altitudeAccuracy, canProvideHeading, heading, canProvideSpeed, speed));
697 #else
698     UNUSED_PARAM(ewkView);
699     UNUSED_PARAM(latitude);
700     UNUSED_PARAM(longitude);
701     UNUSED_PARAM(accuracy);
702     UNUSED_PARAM(canProvideAltitude);
703     UNUSED_PARAM(altitude);
704     UNUSED_PARAM(canProvideAltitudeAccuracy);
705     UNUSED_PARAM(altitudeAccuracy);
706     UNUSED_PARAM(canProvideHeading);
707     UNUSED_PARAM(heading);
708     UNUSED_PARAM(canProvideSpeed);
709     UNUSED_PARAM(speed);
710 #endif
711 }
712
713 void DumpRenderTreeSupportEfl::setMockGeolocationPositionUnavailableError(const Evas_Object* ewkView, const char* errorMessage)
714 {
715 #if ENABLE(GEOLOCATION)
716     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page);
717
718     WebCore::GeolocationClientMock* mock = static_cast<WebCore::GeolocationClientMock*>(WebCore::GeolocationController::from(page)->client());
719     mock->setPositionUnavailableError(errorMessage);
720 #else
721     UNUSED_PARAM(ewkView);
722     UNUSED_PARAM(errorMessage);
723 #endif
724 }
725
726 int DumpRenderTreeSupportEfl::numberOfPendingGeolocationPermissionRequests(const Evas_Object* ewkView)
727 {
728 #if ENABLE(GEOLOCATION)
729     DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page, -1);
730
731     WebCore::GeolocationClientMock* mock = static_cast<WebCore::GeolocationClientMock*>(WebCore::GeolocationController::from(page)->client());
732     return mock->numberOfPendingPermissionRequests();
733 #else
734     UNUSED_PARAM(ewkView);
735     return 0;
736 #endif
737 }
738
739 #if HAVE(ACCESSIBILITY)
740 AtkObject* DumpRenderTreeSupportEfl::rootAccessibleElement(const Evas_Object* ewkFrame)
741 {
742     DRT_SUPPORT_FRAME_GET_OR_RETURN(ewkFrame, frame, 0);
743
744     if (!WebCore::AXObjectCache::accessibilityEnabled())
745         WebCore::AXObjectCache::enableAccessibility();
746
747     if (!frame->document())
748         return 0;
749
750     AtkObject* wrapper = frame->document()->axObjectCache()->rootObject()->wrapper();
751     if (!wrapper)
752         return 0;
753
754     return wrapper;
755 }
756
757 AtkObject* DumpRenderTreeSupportEfl::focusedAccessibleElement(const Evas_Object* ewkFrame)
758 {
759     AtkObject* wrapper = rootAccessibleElement(ewkFrame);
760     if (!wrapper)
761         return 0;
762
763     return webkitAccessibleGetFocusedElement(WEBKIT_ACCESSIBLE(wrapper));
764 }
765 #endif