2 Copyright (C) 2011 ProFUSION embedded systems
3 Copyright (C) 2011 Samsung Electronics
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.
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.
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.
22 #include "DumpRenderTreeSupportEfl.h"
24 #include "FrameLoaderClientEfl.h"
25 #include "ewk_private.h"
27 #include <AnimationController.h>
28 #include <CSSComputedStyleDeclaration.h>
29 #include <DocumentLoader.h>
30 #include <EditorClientEfl.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>
40 #include <JSCSSStyleDeclaration.h>
41 #include <JSElement.h>
42 #include <PageGroup.h>
43 #include <PrintContext.h>
44 #include <RenderTreeAsText.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>
52 unsigned DumpRenderTreeSupportEfl::activeAnimationsCount(const Evas_Object* ewkFrame)
54 WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
59 WebCore::AnimationController* animationController = frame->animation();
61 if (!animationController)
64 return animationController->numberOfActiveAnimations(frame->document());
67 bool DumpRenderTreeSupportEfl::callShouldCloseOnWebView(Evas_Object* ewkFrame)
69 WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
74 return frame->loader()->shouldClose();
77 void DumpRenderTreeSupportEfl::clearFrameName(Evas_Object* ewkFrame)
79 if (WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame))
80 frame->tree()->clearName();
83 void DumpRenderTreeSupportEfl::clearOpener(Evas_Object* ewkFrame)
85 if (WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame))
86 frame->loader()->setOpener(0);
89 String DumpRenderTreeSupportEfl::counterValueByElementId(const Evas_Object* ewkFrame, const char* elementId)
91 WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
96 WebCore::Element* element = frame->document()->getElementById(elementId);
101 return WebCore::counterValueForElement(element);
104 bool DumpRenderTreeSupportEfl::elementDoesAutoCompleteForElementWithId(const Evas_Object* ewkFrame, const String& elementId)
106 WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
111 WebCore::Document* document = frame->document();
114 WebCore::HTMLInputElement* inputElement = static_cast<WebCore::HTMLInputElement*>(document->getElementById(elementId));
119 return inputElement->isTextField() && !inputElement->isPasswordField() && inputElement->shouldAutocomplete();
122 Eina_List* DumpRenderTreeSupportEfl::frameChildren(const Evas_Object* ewkFrame)
124 WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
129 Eina_List* childFrames = 0;
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());
138 childFrames = eina_list_append(childFrames, client->webFrame());
144 WebCore::Frame* DumpRenderTreeSupportEfl::frameParent(const Evas_Object* ewkFrame)
146 WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
151 return frame->tree()->parent();
154 void DumpRenderTreeSupportEfl::layoutFrame(Evas_Object* ewkFrame)
156 WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
161 WebCore::FrameView* frameView = frame->view();
169 int DumpRenderTreeSupportEfl::numberOfPages(const Evas_Object* ewkFrame, float pageWidth, float pageHeight)
171 WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
176 return WebCore::PrintContext::numberOfPages(frame, WebCore::FloatSize(pageWidth, pageHeight));
179 int DumpRenderTreeSupportEfl::numberOfPagesForElementId(const Evas_Object* ewkFrame, const char* elementId, float pageWidth, float pageHeight)
181 WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
186 WebCore::Element *element = frame->document()->getElementById(elementId);
191 return WebCore::PrintContext::pageNumberForElement(element, WebCore::FloatSize(pageWidth, pageHeight));
194 String DumpRenderTreeSupportEfl::pageSizeAndMarginsInPixels(const Evas_Object* ewkFrame, int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft)
196 WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
201 return WebCore::PrintContext::pageSizeAndMarginsInPixels(frame, pageNumber, width, height, marginTop, marginRight, marginBottom, marginLeft);
204 String DumpRenderTreeSupportEfl::pageProperty(const Evas_Object* ewkFrame, const char* propertyName, int pageNumber)
206 WebCore::Frame* coreFrame = EWKPrivate::coreFrame(ewkFrame);
210 return WebCore::PrintContext::pageProperty(coreFrame, propertyName, pageNumber);
213 bool DumpRenderTreeSupportEfl::pauseAnimation(Evas_Object* ewkFrame, const char* name, const char* elementId, double time)
215 WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
220 WebCore::Element* element = frame->document()->getElementById(elementId);
222 if (!element || !element->renderer())
225 return frame->animation()->pauseAnimationAtTime(element->renderer(), name, time);
228 bool DumpRenderTreeSupportEfl::pauseTransition(Evas_Object* ewkFrame, const char* name, const char* elementId, double time)
230 WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
235 WebCore::Element* element = frame->document()->getElementById(elementId);
237 if (!element || !element->renderer())
240 return frame->animation()->pauseTransitionAtTime(element->renderer(), name, time);
243 unsigned DumpRenderTreeSupportEfl::pendingUnloadEventCount(const Evas_Object* ewkFrame)
245 if (WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame))
246 return frame->domWindow()->pendingUnloadEventListeners();
251 String DumpRenderTreeSupportEfl::renderTreeDump(Evas_Object* ewkFrame)
253 WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
258 WebCore::FrameView *frameView = frame->view();
260 if (frameView && frameView->layoutPending())
263 return WebCore::externalRepresentation(frame);
266 String DumpRenderTreeSupportEfl::responseMimeType(const Evas_Object* ewkFrame)
268 WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
273 WebCore::DocumentLoader *documentLoader = frame->loader()->documentLoader();
278 return documentLoader->responseMIMEType();
281 void DumpRenderTreeSupportEfl::resumeAnimations(Evas_Object* ewkFrame)
283 WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
288 WebCore::AnimationController *animationController = frame->animation();
289 if (animationController)
290 animationController->resumeAnimations();
293 WebCore::IntRect DumpRenderTreeSupportEfl::selectionRectangle(const Evas_Object* ewkFrame)
295 WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
298 return WebCore::IntRect();
300 return enclosingIntRect(frame->selection()->bounds());
303 // Compare with "WebKit/Tools/DumpRenderTree/mac/FrameLoadDelegate.mm
304 String DumpRenderTreeSupportEfl::suitableDRTFrameName(const Evas_Object* ewkFrame)
306 WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
311 const String frameName(ewk_frame_name_get(ewkFrame));
313 if (ewkFrame == ewk_view_frame_main_get(ewk_frame_view_get(ewkFrame))) {
314 if (!frameName.isEmpty())
315 return String("main frame \"") + frameName + String("\"");
317 return String("main frame");
320 if (!frameName.isEmpty())
321 return String("frame \"") + frameName + String("\"");
323 return String("frame (anonymous)");
326 void DumpRenderTreeSupportEfl::suspendAnimations(Evas_Object* ewkFrame)
328 WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame);
333 WebCore::AnimationController *animationController = frame->animation();
334 if (animationController)
335 animationController->suspendAnimations();
338 void DumpRenderTreeSupportEfl::setValueForUser(JSContextRef context, JSValueRef nodeObject, const String& value)
340 JSC::ExecState* exec = toJS(context);
341 WebCore::Element* element = WebCore::toElement(toJS(exec, nodeObject));
344 WebCore::HTMLInputElement* inputElement = element->toInputElement();
348 inputElement->setValueForUser(value);
351 void DumpRenderTreeSupportEfl::setAutofilled(JSContextRef context, JSValueRef nodeObject, bool autofilled)
353 JSC::ExecState* exec = toJS(context);
354 WebCore::Element* element = WebCore::toElement(toJS(exec, nodeObject));
357 WebCore::HTMLInputElement* inputElement = element->toInputElement();
361 inputElement->setAutofilled(autofilled);
364 void DumpRenderTreeSupportEfl::setDefersLoading(Evas_Object* ewkView, bool defers)
366 WebCore::Page* page = EWKPrivate::corePage(ewkView);
371 page->setDefersLoading(defers);
374 void DumpRenderTreeSupportEfl::setLoadsSiteIconsIgnoringImageLoadingSetting(Evas_Object* ewkView, bool loadsSiteIconsIgnoringImageLoadingPreferences)
376 WebCore::Page* page = EWKPrivate::corePage(ewkView);
380 page->settings()->setLoadsSiteIconsIgnoringImageLoadingSetting(loadsSiteIconsIgnoringImageLoadingPreferences);
383 void DumpRenderTreeSupportEfl::addUserStyleSheet(const Evas_Object* ewkView, const String& sourceCode, bool allFrames)
385 WebCore::Page* page = EWKPrivate::corePage(ewkView);
389 page->group().addUserStyleSheetToWorld(WebCore::mainThreadNormalWorld(), sourceCode, WebCore::KURL(), nullptr, nullptr, allFrames ? WebCore::InjectInAllFrames : WebCore::InjectInTopFrameOnly);
392 void DumpRenderTreeSupportEfl::executeCoreCommandByName(const Evas_Object* ewkView, const char* name, const char* value)
394 WebCore::Page* page = EWKPrivate::corePage(ewkView);
398 page->focusController()->focusedOrMainFrame()->editor()->command(name).execute(value);
401 bool DumpRenderTreeSupportEfl::findString(const Evas_Object* ewkView, const String& text, WebCore::FindOptions options)
403 WebCore::Page* page = EWKPrivate::corePage(ewkView);
408 return page->findString(text, options);
411 void DumpRenderTreeSupportEfl::setJavaScriptProfilingEnabled(const Evas_Object* ewkView, bool enabled)
413 #if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(INSPECTOR)
414 WebCore::Page* corePage = EWKPrivate::corePage(ewkView);
418 WebCore::InspectorController* controller = corePage->inspectorController();
423 controller->enableProfiler();
425 controller->disableProfiler();
429 bool DumpRenderTreeSupportEfl::isCommandEnabled(const Evas_Object* ewkView, const char* name)
431 WebCore::Page* page = EWKPrivate::corePage(ewkView);
435 return page->focusController()->focusedOrMainFrame()->editor()->command(name).isEnabled();
438 void DumpRenderTreeSupportEfl::setSmartInsertDeleteEnabled(Evas_Object* ewkView, bool enabled)
440 WebCore::Page* page = EWKPrivate::corePage(ewkView);
444 WebCore::EditorClientEfl* editorClient = static_cast<WebCore::EditorClientEfl*>(page->editorClient());
448 editorClient->setSmartInsertDeleteEnabled(enabled);
451 void DumpRenderTreeSupportEfl::setSelectTrailingWhitespaceEnabled(Evas_Object* ewkView, bool enabled)
453 WebCore::Page* page = EWKPrivate::corePage(ewkView);
457 WebCore::EditorClientEfl* editorClient = static_cast<WebCore::EditorClientEfl*>(page->editorClient());
461 editorClient->setSelectTrailingWhitespaceEnabled(enabled);
464 void DumpRenderTreeSupportEfl::garbageCollectorCollect()
466 WebCore::gcController().garbageCollectNow();
469 void DumpRenderTreeSupportEfl::garbageCollectorCollectOnAlternateThread(bool waitUntilDone)
471 WebCore::gcController().garbageCollectOnAlternateThreadForDebugging(waitUntilDone);
474 size_t DumpRenderTreeSupportEfl::javaScriptObjectsCount()
476 return WebCore::JSDOMWindow::commonJSGlobalData()->heap.objectCount();
479 unsigned DumpRenderTreeSupportEfl::workerThreadCount()
482 return WebCore::WorkerThread::workerThreadCount();
488 HistoryItemChildrenVector DumpRenderTreeSupportEfl::childHistoryItems(const Ewk_History_Item* ewkHistoryItem)
490 WebCore::HistoryItem* historyItem = EWKPrivate::coreHistoryItem(ewkHistoryItem);
491 HistoryItemChildrenVector kids;
496 const WebCore::HistoryItemVector& children = historyItem->children();
497 const unsigned size = children.size();
499 for (unsigned i = 0; i < size; ++i) {
500 Ewk_History_Item* kid = ewk_history_item_new_from_core(children[i].get());
507 String DumpRenderTreeSupportEfl::historyItemTarget(const Ewk_History_Item* ewkHistoryItem)
509 WebCore::HistoryItem* historyItem = EWKPrivate::coreHistoryItem(ewkHistoryItem);
514 return historyItem->target();
517 bool DumpRenderTreeSupportEfl::isTargetItem(const Ewk_History_Item* ewkHistoryItem)
519 WebCore::HistoryItem* historyItem = EWKPrivate::coreHistoryItem(ewkHistoryItem);
524 return historyItem->isTargetItem();
527 void DumpRenderTreeSupportEfl::setMockScrollbarsEnabled(bool enable)
529 WebCore::Settings::setMockScrollbarsEnabled(enable);
532 void DumpRenderTreeSupportEfl::dumpConfigurationForViewport(Evas_Object* ewkView, int deviceDPI, const WebCore::IntSize& deviceSize, const WebCore::IntSize& availableSize)
534 WebCore::Page* page = EWKPrivate::corePage(ewkView);
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(),
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);
549 void DumpRenderTreeSupportEfl::deliverAllMutationsIfNecessary()
551 #if ENABLE(MUTATION_OBSERVERS)
552 WebCore::WebKitMutationObserver::deliverAllMutations();
556 void DumpRenderTreeSupportEfl::setEditingBehavior(Evas_Object* ewkView, const char* editingBehavior)
558 WebCore::EditingBehaviorType coreEditingBehavior;
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;
567 ASSERT_NOT_REACHED();
571 WebCore::Page* corePage = EWKPrivate::corePage(ewkView);
575 corePage->settings()->setEditingBehaviorType(coreEditingBehavior);
578 String DumpRenderTreeSupportEfl::markerTextForListItem(JSContextRef context, JSValueRef nodeObject)
580 JSC::ExecState* exec = toJS(context);
581 WebCore::Element* element = WebCore::toElement(toJS(exec, nodeObject));
585 return WebCore::markerTextForListItem(element);
588 void DumpRenderTreeSupportEfl::setInteractiveFormValidationEnabled(Evas_Object* ewkView, bool enabled)
590 WebCore::Page* corePage = EWKPrivate::corePage(ewkView);
592 corePage->settings()->setInteractiveFormValidationEnabled(enabled);
595 JSValueRef DumpRenderTreeSupportEfl::computedStyleIncludingVisitedInfo(JSContextRef context, JSValueRef value)
598 return JSValueMakeUndefined(context);
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);
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()));
611 void DumpRenderTreeSupportEfl::setAuthorAndUserStylesEnabled(Evas_Object* ewkView, bool enabled)
613 WebCore::Page* corePage = EWKPrivate::corePage(ewkView);
617 corePage->settings()->setAuthorAndUserStylesEnabled(enabled);
620 void DumpRenderTreeSupportEfl::setComposition(Evas_Object* ewkView, const char* text, int start, int length)
622 WebCore::Page* page = EWKPrivate::corePage(ewkView);
623 if (!page || !page->focusController() || !page->focusController()->focusedOrMainFrame())
626 WebCore::Editor* editor = page->focusController()->focusedOrMainFrame()->editor();
627 if (!editor || (!editor->canEdit() && !editor->hasComposition()))
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);
636 bool DumpRenderTreeSupportEfl::hasComposition(const Evas_Object* ewkView)
638 const WebCore::Page* page = EWKPrivate::corePage(ewkView);
639 if (!page || !page->focusController() || !page->focusController()->focusedOrMainFrame())
642 const WebCore::Editor* editor = page->focusController()->focusedOrMainFrame()->editor();
646 return editor->hasComposition();
649 bool DumpRenderTreeSupportEfl::compositionRange(Evas_Object* ewkView, int* start, int* length)
651 *start = *length = 0;
653 WebCore::Page* page = EWKPrivate::corePage(ewkView);
654 if (!page || !page->focusController() || !page->focusController()->focusedOrMainFrame())
657 WebCore::Editor* editor = page->focusController()->focusedOrMainFrame()->editor();
658 if (!editor || !editor->hasComposition())
661 *start = editor->compositionStart();
662 *length = editor->compositionEnd() - *start;
666 void DumpRenderTreeSupportEfl::confirmComposition(Evas_Object* ewkView, const char* text)
668 WebCore::Page* page = EWKPrivate::corePage(ewkView);
669 if (!page || !page->focusController() || !page->focusController()->focusedOrMainFrame())
672 WebCore::Editor* editor = page->focusController()->focusedOrMainFrame()->editor();
676 if (!editor->hasComposition()) {
677 editor->insertText(String::fromUTF8(text), 0);
682 editor->confirmComposition(String::fromUTF8(text));
685 editor->confirmComposition();
688 WebCore::IntRect DumpRenderTreeSupportEfl::firstRectForCharacterRange(Evas_Object* ewkView, int location, int length)
690 WebCore::Page* page = EWKPrivate::corePage(ewkView);
691 if (!page || !page->focusController() || !page->focusController()->focusedOrMainFrame() || !page->focusController()->focusedOrMainFrame()->editor())
692 return WebCore::IntRect();
694 if ((location + length < location) && (location + length))
697 WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
698 WebCore::Editor* editor = frame->editor();
700 RefPtr<WebCore::Range> range = WebCore::TextIterator::rangeFromLocationAndLength(frame->selection()->rootEditableElementOrDocumentElement(), location, length);
702 return WebCore::IntRect();
704 return editor->firstRectForRange(range.get());
707 bool DumpRenderTreeSupportEfl::selectedRange(Evas_Object* ewkView, int* start, int* length)
709 if (!(start && length))
712 WebCore::Page* page = EWKPrivate::corePage(ewkView);
713 if (!page || !page->focusController() || !page->focusController()->focusedOrMainFrame())
716 WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
717 RefPtr<WebCore::Range> range = frame->selection()->toNormalizedRange().get();
721 WebCore::Element* selectionRoot = frame->selection()->rootEditableElement();
722 WebCore::Element* scope = selectionRoot ? selectionRoot : frame->document()->documentElement();
724 RefPtr<WebCore::Range> testRange = WebCore::Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset());
725 *start = WebCore::TextIterator::rangeLength(testRange.get());
727 WebCore::ExceptionCode ec;
728 testRange->setEnd(range->endContainer(), range->endOffset(), ec);
729 *length = WebCore::TextIterator::rangeLength(testRange.get());