967c2bb6e7a488ec630b0b08d4060d1b1c5306af
[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 <WebKitMutationObserver.h>
47 #include <bindings/js/GCController.h>
48 #include <history/HistoryItem.h>
49 #include <workers/WorkerThread.h>
50
51 unsigned DumpRenderTreeSupportEfl::activeAnimationsCount(const Evas_Object* ewkFrame)
52 {
53     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
54
55     if (!frame)
56         return 0;
57
58     WebCore::AnimationController* animationController = frame->animation();
59
60     if (!animationController)
61         return 0;
62
63     return animationController->numberOfActiveAnimations(frame->document());
64 }
65
66 bool DumpRenderTreeSupportEfl::callShouldCloseOnWebView(Evas_Object* ewkFrame)
67 {
68     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
69
70     if (!frame)
71         return false;
72
73     return frame->loader()->shouldClose();
74 }
75
76 void DumpRenderTreeSupportEfl::clearFrameName(Evas_Object* ewkFrame)
77 {
78     if (WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame))
79         frame->tree()->clearName();
80 }
81
82 void DumpRenderTreeSupportEfl::clearOpener(Evas_Object* ewkFrame)
83 {
84     if (WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame))
85         frame->loader()->setOpener(0);
86 }
87
88 String DumpRenderTreeSupportEfl::counterValueByElementId(const Evas_Object* ewkFrame, const char* elementId)
89 {
90     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
91
92     if (!frame)
93         return String();
94
95     WebCore::Element* element = frame->document()->getElementById(elementId);
96
97     if (!element)
98         return String();
99
100     return WebCore::counterValueForElement(element);
101 }
102
103 bool DumpRenderTreeSupportEfl::elementDoesAutoCompleteForElementWithId(const Evas_Object* ewkFrame, const String& elementId)
104 {
105     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
106
107     if (!frame)
108         return false;
109
110     WebCore::Document* document = frame->document();
111     ASSERT(document);
112
113     WebCore::HTMLInputElement* inputElement = static_cast<WebCore::HTMLInputElement*>(document->getElementById(elementId));
114
115     if (!inputElement)
116         return false;
117
118     return inputElement->isTextField() && !inputElement->isPasswordField() && inputElement->shouldAutocomplete();
119 }
120
121 Eina_List* DumpRenderTreeSupportEfl::frameChildren(const Evas_Object* ewkFrame)
122 {
123     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
124
125     if (!frame)
126         return 0;
127
128     Eina_List* childFrames = 0;
129
130     for (unsigned index = 0; index < frame->tree()->childCount(); index++) {
131         WebCore::Frame *childFrame = frame->tree()->child(index);
132         WebCore::FrameLoaderClientEfl *client = static_cast<WebCore::FrameLoaderClientEfl*>(childFrame->loader()->client());
133
134         if (!client)
135             continue;
136
137         childFrames = eina_list_append(childFrames, client->webFrame());
138     }
139
140     return childFrames;
141 }
142
143 WebCore::Frame* DumpRenderTreeSupportEfl::frameParent(const Evas_Object* ewkFrame)
144 {
145     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
146
147     if (!frame)
148         return 0;
149
150     return frame->tree()->parent();
151 }
152
153 void DumpRenderTreeSupportEfl::layoutFrame(Evas_Object* ewkFrame)
154 {
155     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
156
157     if (!frame)
158         return;
159
160     WebCore::FrameView* frameView = frame->view();
161
162     if (!frameView)
163         return;
164
165     frameView->layout();
166 }
167
168 int DumpRenderTreeSupportEfl::numberOfPages(const Evas_Object* ewkFrame, float pageWidth, float pageHeight)
169 {
170     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
171
172     if (!frame)
173         return 0;
174
175     return WebCore::PrintContext::numberOfPages(frame, WebCore::FloatSize(pageWidth, pageHeight));
176 }
177
178 int DumpRenderTreeSupportEfl::numberOfPagesForElementId(const Evas_Object* ewkFrame, const char* elementId, float pageWidth, float pageHeight)
179 {
180     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
181
182     if (!frame)
183         return 0;
184
185     WebCore::Element *element = frame->document()->getElementById(elementId);
186
187     if (!element)
188         return 0;
189
190     return WebCore::PrintContext::pageNumberForElement(element, WebCore::FloatSize(pageWidth, pageHeight));
191 }
192
193 String DumpRenderTreeSupportEfl::pageSizeAndMarginsInPixels(const Evas_Object* ewkFrame, int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft)
194 {
195     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
196
197     if (!frame)
198         return String();
199
200     return WebCore::PrintContext::pageSizeAndMarginsInPixels(frame, pageNumber, width, height, marginTop, marginRight, marginBottom, marginLeft);
201 }
202
203 String DumpRenderTreeSupportEfl::pageProperty(const Evas_Object* ewkFrame, const char* propertyName, int pageNumber)
204 {
205     WebCore::Frame* coreFrame = EWKPrivate::coreFrame(ewkFrame);
206     if (!coreFrame)
207         return String();
208
209     return WebCore::PrintContext::pageProperty(coreFrame, propertyName, pageNumber);
210 }
211
212 bool DumpRenderTreeSupportEfl::pauseAnimation(Evas_Object* ewkFrame, const char* name, const char* elementId, double time)
213 {
214     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
215
216     if (!frame)
217         return false;
218
219     WebCore::Element* element = frame->document()->getElementById(elementId);
220
221     if (!element || !element->renderer())
222         return false;
223
224     return frame->animation()->pauseAnimationAtTime(element->renderer(), name, time);
225 }
226
227 bool DumpRenderTreeSupportEfl::pauseTransition(Evas_Object* ewkFrame, const char* name, const char* elementId, double time)
228 {
229     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
230
231     if (!frame)
232         return false;
233
234     WebCore::Element* element = frame->document()->getElementById(elementId);
235
236     if (!element || !element->renderer())
237         return false;
238
239     return frame->animation()->pauseTransitionAtTime(element->renderer(), name, time);
240 }
241
242 unsigned DumpRenderTreeSupportEfl::pendingUnloadEventCount(const Evas_Object* ewkFrame)
243 {
244     if (WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame))
245         return frame->domWindow()->pendingUnloadEventListeners();
246
247     return 0;
248 }
249
250 String DumpRenderTreeSupportEfl::renderTreeDump(Evas_Object* ewkFrame)
251 {
252     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
253
254     if (!frame)
255         return String();
256
257     WebCore::FrameView *frameView = frame->view();
258
259     if (frameView && frameView->layoutPending())
260         frameView->layout();
261
262     return WebCore::externalRepresentation(frame);
263 }
264
265 String DumpRenderTreeSupportEfl::responseMimeType(const Evas_Object* ewkFrame)
266 {
267     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
268
269     if (!frame)
270         return String();
271
272     WebCore::DocumentLoader *documentLoader = frame->loader()->documentLoader();
273
274     if (!documentLoader)
275         return String();
276
277     return documentLoader->responseMIMEType();
278 }
279
280 void DumpRenderTreeSupportEfl::resumeAnimations(Evas_Object* ewkFrame)
281 {
282     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
283
284     if (!frame)
285         return;
286
287     WebCore::AnimationController *animationController = frame->animation();
288     if (animationController)
289         animationController->resumeAnimations();
290 }
291
292 WebCore::IntRect DumpRenderTreeSupportEfl::selectionRectangle(const Evas_Object* ewkFrame)
293 {
294     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
295
296     if (!frame)
297         return WebCore::IntRect();
298
299     return enclosingIntRect(frame->selection()->bounds());
300 }
301
302 // Compare with "WebKit/Tools/DumpRenderTree/mac/FrameLoadDelegate.mm
303 String DumpRenderTreeSupportEfl::suitableDRTFrameName(const Evas_Object* ewkFrame)
304 {
305     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
306
307     if (!frame)
308         return String();
309
310     const String frameName(ewk_frame_name_get(ewkFrame));
311
312     if (ewkFrame == ewk_view_frame_main_get(ewk_frame_view_get(ewkFrame))) {
313         if (!frameName.isEmpty())
314             return String("main frame \"") + frameName + String("\"");
315
316         return String("main frame");
317     }
318
319     if (!frameName.isEmpty())
320         return String("frame \"") + frameName + String("\"");
321
322     return String("frame (anonymous)");
323 }
324
325 void DumpRenderTreeSupportEfl::suspendAnimations(Evas_Object* ewkFrame)
326 {
327     WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
328
329     if (!frame)
330         return;
331
332     WebCore::AnimationController *animationController = frame->animation();
333     if (animationController)
334         animationController->suspendAnimations();
335 }
336
337 void DumpRenderTreeSupportEfl::setValueForUser(JSContextRef context, JSValueRef nodeObject, const String& value)
338 {
339     JSC::ExecState* exec = toJS(context);
340     WebCore::Element* element = WebCore::toElement(toJS(exec, nodeObject));
341     if (!element)
342         return;
343     WebCore::HTMLInputElement* inputElement = element->toInputElement();
344     if (!inputElement)
345         return;
346
347     inputElement->setValueForUser(value);
348 }
349
350 void DumpRenderTreeSupportEfl::setAutofilled(JSContextRef context, JSValueRef nodeObject, bool autofilled)
351 {
352     JSC::ExecState* exec = toJS(context);
353     WebCore::Element* element = WebCore::toElement(toJS(exec, nodeObject));
354     if (!element)
355         return;
356     WebCore::HTMLInputElement* inputElement = element->toInputElement();
357     if (!inputElement)
358         return;
359
360     inputElement->setAutofilled(autofilled);
361 }
362
363 void DumpRenderTreeSupportEfl::setDefersLoading(Evas_Object* ewkView, bool defers)
364 {
365     WebCore::Page* page = EWKPrivate::corePage(ewkView);
366
367     if (!page)
368         return;
369
370     page->setDefersLoading(defers);
371 }
372
373 void DumpRenderTreeSupportEfl::setLoadsSiteIconsIgnoringImageLoadingSetting(Evas_Object* ewkView, bool loadsSiteIconsIgnoringImageLoadingPreferences)
374 {
375     WebCore::Page* page = EWKPrivate::corePage(ewkView);
376     if (!page)
377         return;
378
379     page->settings()->setLoadsSiteIconsIgnoringImageLoadingSetting(loadsSiteIconsIgnoringImageLoadingPreferences);
380 }
381
382 void DumpRenderTreeSupportEfl::addUserStyleSheet(const Evas_Object* ewkView, const String& sourceCode, bool allFrames)
383 {
384     WebCore::Page* page = EWKPrivate::corePage(ewkView);
385     if (!page)
386         return;
387
388     page->group().addUserStyleSheetToWorld(WebCore::mainThreadNormalWorld(), sourceCode, WebCore::KURL(), nullptr, nullptr, allFrames ? WebCore::InjectInAllFrames : WebCore::InjectInTopFrameOnly);
389 }
390
391 void DumpRenderTreeSupportEfl::executeCoreCommandByName(const Evas_Object* ewkView, const char* name, const char* value)
392 {
393     WebCore::Page* page = EWKPrivate::corePage(ewkView);
394     if (!page)
395         return;
396
397     page->focusController()->focusedOrMainFrame()->editor()->command(name).execute(value);
398 }
399
400 bool DumpRenderTreeSupportEfl::findString(const Evas_Object* ewkView, const String& text, WebCore::FindOptions options)
401 {
402     WebCore::Page* page = EWKPrivate::corePage(ewkView);
403
404     if (!page)
405         return false;
406
407     return page->findString(text, options);
408 }
409
410 void DumpRenderTreeSupportEfl::setJavaScriptProfilingEnabled(const Evas_Object* ewkView, bool enabled)
411 {
412 #if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(INSPECTOR)
413     WebCore::Page* corePage = EWKPrivate::corePage(ewkView);
414     if (!corePage)
415         return;
416
417     WebCore::InspectorController* controller = corePage->inspectorController();
418     if (!controller)
419         return;
420
421     if (enabled)
422         controller->enableProfiler();
423     else
424         controller->disableProfiler();
425 #endif
426 }
427
428 bool DumpRenderTreeSupportEfl::isCommandEnabled(const Evas_Object* ewkView, const char* name)
429 {
430     WebCore::Page* page = EWKPrivate::corePage(ewkView);
431     if (!page)
432         return false;
433
434     return page->focusController()->focusedOrMainFrame()->editor()->command(name).isEnabled();
435 }
436
437 void DumpRenderTreeSupportEfl::setSmartInsertDeleteEnabled(Evas_Object* ewkView, bool enabled)
438 {
439     WebCore::Page* page = EWKPrivate::corePage(ewkView);
440     if (!page)
441         return;
442
443     WebCore::EditorClientEfl* editorClient = static_cast<WebCore::EditorClientEfl*>(page->editorClient());
444     if (!editorClient)
445         return;
446
447     editorClient->setSmartInsertDeleteEnabled(enabled);
448 }
449
450 void DumpRenderTreeSupportEfl::setSelectTrailingWhitespaceEnabled(Evas_Object* ewkView, bool enabled)
451 {
452     WebCore::Page* page = EWKPrivate::corePage(ewkView);
453     if (!page)
454         return;
455
456     WebCore::EditorClientEfl* editorClient = static_cast<WebCore::EditorClientEfl*>(page->editorClient());
457     if (!editorClient)
458         return;
459
460     editorClient->setSelectTrailingWhitespaceEnabled(enabled);
461 }
462
463 void DumpRenderTreeSupportEfl::garbageCollectorCollect()
464 {
465     WebCore::gcController().garbageCollectNow();
466 }
467
468 void DumpRenderTreeSupportEfl::garbageCollectorCollectOnAlternateThread(bool waitUntilDone)
469 {
470     WebCore::gcController().garbageCollectOnAlternateThreadForDebugging(waitUntilDone);
471 }
472
473 size_t DumpRenderTreeSupportEfl::javaScriptObjectsCount()
474 {
475     return WebCore::JSDOMWindow::commonJSGlobalData()->heap.objectCount();
476 }
477
478 unsigned DumpRenderTreeSupportEfl::workerThreadCount()
479 {
480 #if ENABLE(WORKERS)
481     return WebCore::WorkerThread::workerThreadCount();
482 #else
483     return 0;
484 #endif
485 }
486
487 HistoryItemChildrenVector DumpRenderTreeSupportEfl::childHistoryItems(const Ewk_History_Item* ewkHistoryItem)
488 {
489     WebCore::HistoryItem* historyItem = EWKPrivate::coreHistoryItem(ewkHistoryItem);
490     HistoryItemChildrenVector kids;
491
492     if (!historyItem)
493         return kids;
494
495     const WebCore::HistoryItemVector& children = historyItem->children();
496     const unsigned size = children.size();
497
498     for (unsigned i = 0; i < size; ++i) {
499         Ewk_History_Item* kid = ewk_history_item_new_from_core(children[i].get());
500         kids.append(kid);
501     }
502
503     return kids;
504 }
505
506 String DumpRenderTreeSupportEfl::historyItemTarget(const Ewk_History_Item* ewkHistoryItem)
507 {
508     WebCore::HistoryItem* historyItem = EWKPrivate::coreHistoryItem(ewkHistoryItem);
509
510     if (!historyItem)
511         return String();
512
513     return historyItem->target();
514 }
515
516 bool DumpRenderTreeSupportEfl::isTargetItem(const Ewk_History_Item* ewkHistoryItem)
517 {
518     WebCore::HistoryItem* historyItem = EWKPrivate::coreHistoryItem(ewkHistoryItem);
519
520     if (!historyItem)
521         return false;
522
523     return historyItem->isTargetItem();
524 }
525
526 void DumpRenderTreeSupportEfl::setMockScrollbarsEnabled(bool enable)
527 {
528     WebCore::Settings::setMockScrollbarsEnabled(enable);
529 }
530
531 void DumpRenderTreeSupportEfl::dumpConfigurationForViewport(Evas_Object* ewkView, int deviceDPI, const WebCore::IntSize& deviceSize, const WebCore::IntSize& availableSize)
532 {
533     WebCore::Page* page = EWKPrivate::corePage(ewkView);
534
535     if (!page)
536         return;
537     WebCore::ViewportArguments arguments = page->mainFrame()->document()->viewportArguments();
538     WebCore::ViewportAttributes attributes = computeViewportAttributes(arguments,
539             /* default layout width for non-mobile pages */ 980,
540             deviceSize.width(), deviceSize.height(),
541             deviceDPI,
542             availableSize);
543     restrictMinimumScaleFactorToViewportSize(attributes, availableSize);
544     restrictScaleFactorToInitialScaleIfNotUserScalable(attributes);
545     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);
546 }
547
548 void DumpRenderTreeSupportEfl::deliverAllMutationsIfNecessary()
549 {
550 #if ENABLE(MUTATION_OBSERVERS)
551     WebCore::WebKitMutationObserver::deliverAllMutations();
552 #endif
553 }
554
555 void DumpRenderTreeSupportEfl::setEditingBehavior(Evas_Object* ewkView, const char* editingBehavior)
556 {
557     WebCore::EditingBehaviorType coreEditingBehavior;
558
559     if (!strcmp(editingBehavior, "win"))
560         coreEditingBehavior = WebCore::EditingWindowsBehavior;
561     else if (!strcmp(editingBehavior, "mac"))
562         coreEditingBehavior = WebCore::EditingMacBehavior;
563     else if (!strcmp(editingBehavior, "unix"))
564         coreEditingBehavior = WebCore::EditingUnixBehavior;
565     else {
566         ASSERT_NOT_REACHED();
567         return;
568     }
569
570     WebCore::Page* corePage = EWKPrivate::corePage(ewkView);
571     if (!corePage)
572         return;
573
574     corePage->settings()->setEditingBehaviorType(coreEditingBehavior);
575 }
576
577 String DumpRenderTreeSupportEfl::markerTextForListItem(JSContextRef context, JSValueRef nodeObject)
578 {
579     JSC::ExecState* exec = toJS(context);
580     WebCore::Element* element = WebCore::toElement(toJS(exec, nodeObject));
581     if (!element)
582         return String();
583
584     return WebCore::markerTextForListItem(element);
585 }
586
587 void DumpRenderTreeSupportEfl::setInteractiveFormValidationEnabled(Evas_Object* ewkView, bool enabled)
588 {
589     WebCore::Page* corePage = EWKPrivate::corePage(ewkView);
590     if (corePage)
591         corePage->settings()->setInteractiveFormValidationEnabled(enabled);
592 }
593
594 JSValueRef DumpRenderTreeSupportEfl::computedStyleIncludingVisitedInfo(JSContextRef context, JSValueRef value)
595 {
596     if (!value)
597         return JSValueMakeUndefined(context);
598
599     JSC::ExecState* exec = toJS(context);
600     JSC::JSValue jsValue = toJS(exec, value);
601     if (!jsValue.inherits(&WebCore::JSElement::s_info))
602         return JSValueMakeUndefined(context);
603
604     WebCore::JSElement* jsElement = static_cast<WebCore::JSElement*>(asObject(jsValue));
605     WebCore::Element* element = jsElement->impl();
606     RefPtr<WebCore::CSSComputedStyleDeclaration> style = WebCore::CSSComputedStyleDeclaration::create(element, true);
607     return toRef(exec, toJS(exec, jsElement->globalObject(), style.get()));
608 }
609
610 void DumpRenderTreeSupportEfl::setAuthorAndUserStylesEnabled(Evas_Object* ewkView, bool enabled)
611 {
612     WebCore::Page* corePage = EWKPrivate::corePage(ewkView);
613     if (!corePage)
614         return;
615
616     corePage->settings()->setAuthorAndUserStylesEnabled(enabled);
617 }