2011-04-01 Dominic Cooney <dominicc@google.com>
[WebKit-https.git] / Source / WebKit / gtk / WebCoreSupport / DumpRenderTreeSupportGtk.cpp
1 /*
2  *  Copyright (C) Research In Motion Limited 2010. All rights reserved.
3  *  Copyright (C) 2010 Joone Hur <joone@kldp.org>
4  *  Copyright (C) 2009 Google Inc. All rights reserved.
5  *  Copyright (C) 2011 Igalia S.L.
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Lesser 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  *  Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public
18  *  License along with this library; if not, write to the Free Software
19  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #include "config.h"
23 #include "DumpRenderTreeSupportGtk.h"
24
25 #include "APICast.h"
26 #include "AXObjectCache.h"
27 #include "AccessibilityObjectWrapperAtk.h"
28 #include "AnimationController.h"
29 #include "DOMWrapperWorld.h"
30 #include "Document.h"
31 #include "Element.h"
32 #include "FocusController.h"
33 #include "FrameLoaderClientGtk.h"
34 #include "FrameTree.h"
35 #include "FrameView.h"
36 #include "GCController.h"
37 #include "GraphicsContext.h"
38 #include "HTMLInputElement.h"
39 #include "InputElement.h"
40 #include "JSDOMWindow.h"
41 #include "JSDocument.h"
42 #include "JSElement.h"
43 #include "JSLock.h"
44 #include "JSNodeList.h"
45 #include "JSValue.h"
46 #include "NodeList.h"
47 #include "PageGroup.h"
48 #include "PlatformString.h"
49 #include "PrintContext.h"
50 #include "RenderListItem.h"
51 #include "RenderTreeAsText.h"
52 #include "RenderView.h"
53 #include "SecurityOrigin.h"
54 #include "Settings.h"
55 #include "TextIterator.h"
56 #include "WorkerThread.h"
57 #include "webkitglobalsprivate.h"
58 #include "webkitwebframe.h"
59 #include "webkitwebframeprivate.h"
60 #include "webkitwebview.h"
61 #include "webkitwebviewprivate.h"
62 #include <JavaScriptCore/APICast.h>
63
64 #if ENABLE(SVG)
65 #include "SVGDocumentExtensions.h"
66 #include "SVGSMILElement.h"
67 #endif
68
69 using namespace JSC;
70 using namespace WebCore;
71 using namespace WebKit;
72
73 bool DumpRenderTreeSupportGtk::s_drtRun = false;
74 bool DumpRenderTreeSupportGtk::s_linksIncludedInTabChain = true;
75 bool DumpRenderTreeSupportGtk::s_selectTrailingWhitespaceEnabled = false;
76
77 DumpRenderTreeSupportGtk::DumpRenderTreeSupportGtk()
78 {
79 }
80
81 DumpRenderTreeSupportGtk::~DumpRenderTreeSupportGtk()
82 {
83 }
84
85 void DumpRenderTreeSupportGtk::setDumpRenderTreeModeEnabled(bool enabled)
86 {
87     s_drtRun = enabled;
88 }
89
90 bool DumpRenderTreeSupportGtk::dumpRenderTreeModeEnabled()
91 {
92     return s_drtRun;
93 }
94 void DumpRenderTreeSupportGtk::setLinksIncludedInFocusChain(bool enabled)
95 {
96     s_linksIncludedInTabChain = enabled;
97 }
98
99 bool DumpRenderTreeSupportGtk::linksIncludedInFocusChain()
100 {
101     return s_linksIncludedInTabChain;
102 }
103
104 void DumpRenderTreeSupportGtk::setSelectTrailingWhitespaceEnabled(bool enabled)
105 {
106     s_selectTrailingWhitespaceEnabled = enabled;
107 }
108
109 bool DumpRenderTreeSupportGtk::selectTrailingWhitespaceEnabled()
110 {
111     return s_selectTrailingWhitespaceEnabled;
112 }
113
114 JSValueRef DumpRenderTreeSupportGtk::nodesFromRect(JSContextRef context, JSValueRef value, int x, int y, unsigned top, unsigned right, unsigned bottom, unsigned left, bool ignoreClipping)
115 {
116     JSLock lock(SilenceAssertionsOnly);
117     ExecState* exec = toJS(context);
118     if (!value)
119         return JSValueMakeUndefined(context);
120     JSValue jsValue = toJS(exec, value);
121     if (!jsValue.inherits(&JSDocument::s_info))
122        return JSValueMakeUndefined(context);
123
124     JSDocument* jsDocument = static_cast<JSDocument*>(asObject(jsValue));
125     Document* document = jsDocument->impl();
126     RefPtr<NodeList> nodes = document->nodesFromRect(x, y, top, right, bottom, left, ignoreClipping);
127     return toRef(exec, toJS(exec, jsDocument->globalObject(), nodes.get()));
128 }
129
130 /**
131  * getFrameChildren:
132  * @frame: a #WebKitWebFrame
133  *
134  * Return value: child frames of @frame
135  */
136 GSList* DumpRenderTreeSupportGtk::getFrameChildren(WebKitWebFrame* frame)
137 {
138     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), 0);
139
140     Frame* coreFrame = core(frame);
141     if (!coreFrame)
142         return 0;
143
144     GSList* children = 0;
145     for (Frame* child = coreFrame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
146         FrameLoader* loader = child->loader();
147         WebKit::FrameLoaderClient* client = static_cast<WebKit::FrameLoaderClient*>(loader->client());
148         if (client)
149           children = g_slist_append(children, client->webFrame());
150     }
151
152     return children;
153 }
154
155 /**
156  * getInnerText:
157  * @frame: a #WebKitWebFrame
158  *
159  * Return value: inner text of @frame
160  */
161 CString DumpRenderTreeSupportGtk::getInnerText(WebKitWebFrame* frame)
162 {
163     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), CString(""));
164
165     Frame* coreFrame = core(frame);
166     if (!coreFrame)
167         return CString("");
168
169     FrameView* view = coreFrame->view();
170
171     if (view && view->layoutPending())
172         view->layout();
173
174     Element* documentElement = coreFrame->document()->documentElement();
175     return documentElement->innerText().utf8();
176 }
177
178 /**
179  * dumpRenderTree:
180  * @frame: a #WebKitWebFrame
181  *
182  * Return value: Non-recursive render tree dump of @frame
183  */
184 CString DumpRenderTreeSupportGtk::dumpRenderTree(WebKitWebFrame* frame)
185 {
186     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), CString(""));
187
188     Frame* coreFrame = core(frame);
189     if (!coreFrame)
190         return CString("");
191
192     FrameView* view = coreFrame->view();
193
194     if (view && view->layoutPending())
195         view->layout();
196
197     return externalRepresentation(coreFrame).utf8();
198 }
199
200 /**
201  * counterValueForElementById:
202  * @frame: a #WebKitWebFrame
203  * @id: an element ID string
204  *
205  * Return value: The counter value of element @id in @frame
206  */
207 CString DumpRenderTreeSupportGtk::counterValueForElementById(WebKitWebFrame* frame, const char* id)
208 {
209     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), CString());
210
211     Frame* coreFrame = core(frame);
212     if (!coreFrame)
213         return CString();
214
215     Element* coreElement = coreFrame->document()->getElementById(AtomicString(id));
216     if (!coreElement)
217         return CString();
218
219     return counterValueForElement(coreElement).utf8();
220 }
221
222 /**
223  * numberForElementById
224  * @frame: a #WebKitWebFrame
225  * @id: an element ID string
226  * @pageWidth: width of a page
227  * @pageHeight: height of a page
228  *
229  * Return value: The number of page where the specified element will be put
230  */
231 int DumpRenderTreeSupportGtk::pageNumberForElementById(WebKitWebFrame* frame, const char* id, float pageWidth, float pageHeight)
232 {
233     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), 0);
234
235     Frame* coreFrame = core(frame);
236     if (!coreFrame)
237         return -1;
238
239     Element* coreElement = coreFrame->document()->getElementById(AtomicString(id));
240     if (!coreElement)
241         return -1;
242     return PrintContext::pageNumberForElement(coreElement, FloatSize(pageWidth, pageHeight));
243 }
244
245 /**
246  * numberOfPagesForFrame
247  * @frame: a #WebKitWebFrame
248  * @pageWidth: width of a page
249  * @pageHeight: height of a page
250  *
251  * Return value: The number of pages to be printed.
252  */
253 int DumpRenderTreeSupportGtk::numberOfPagesForFrame(WebKitWebFrame* frame, float pageWidth, float pageHeight)
254 {
255     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), 0);
256
257     Frame* coreFrame = core(frame);
258     if (!coreFrame)
259         return -1;
260
261     return PrintContext::numberOfPages(coreFrame, FloatSize(pageWidth, pageHeight));
262 }
263
264 /**
265  * pageProperty
266  * @frame: a #WebKitWebFrame
267  * @propertyName: name of a property
268  * @pageNumber: number of a page 
269  *
270  * Return value: The value of the given property name.
271  */
272 CString DumpRenderTreeSupportGtk::pageProperty(WebKitWebFrame* frame, const char* propertyName, int pageNumber)
273 {
274     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), CString());
275
276     Frame* coreFrame = core(frame);
277     if (!coreFrame)
278         return CString();
279
280     return PrintContext::pageProperty(coreFrame, propertyName, pageNumber).utf8();
281 }
282
283 /**
284  * isPageBoxVisible
285  * @frame: a #WebKitWebFrame
286  * @pageNumber: number of a page 
287  *
288  * Return value: TRUE if a page box is visible. 
289  */
290 bool DumpRenderTreeSupportGtk::isPageBoxVisible(WebKitWebFrame* frame, int pageNumber)
291 {
292     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), false);
293
294     Frame* coreFrame = core(frame);
295     if (!coreFrame)
296         return false;
297
298     return coreFrame->document()->isPageBoxVisible(pageNumber); 
299 }
300
301 /**
302  * pageSizeAndMarginsInPixels
303  * @frame: a #WebKitWebFrame
304  * @pageNumber: number of a page 
305  * @width: width of a page
306  * @height: height of a page
307  * @marginTop: top margin of a page
308  * @marginRight: right margin of a page
309  * @marginBottom: bottom margin of a page
310  * @marginLeft: left margin of a page
311  *
312  * Return value: The value of page size and margin.
313  */
314 CString DumpRenderTreeSupportGtk::pageSizeAndMarginsInPixels(WebKitWebFrame* frame, int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft)
315 {
316     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), CString());
317
318     Frame* coreFrame = core(frame);
319     if (!coreFrame)
320         return CString();
321
322     return PrintContext::pageSizeAndMarginsInPixels(coreFrame, pageNumber, width, height, marginTop, marginRight, marginBottom, marginLeft).utf8();
323 }
324
325 /**
326  * addUserStyleSheet
327  * @frame: a #WebKitWebFrame
328  * @sourceCode: code of a user stylesheet
329  *
330  */
331 void DumpRenderTreeSupportGtk::addUserStyleSheet(WebKitWebFrame* frame, const char* sourceCode, bool allFrames)
332 {
333     g_return_if_fail(WEBKIT_IS_WEB_FRAME(frame));
334
335     Frame* coreFrame = core(frame);
336     if (!coreFrame)
337         return;
338
339     WebKitWebView* webView = getViewFromFrame(frame);
340     Page* page = core(webView);
341     page->group().addUserStyleSheetToWorld(mainThreadNormalWorld(), sourceCode, KURL(), 0, 0, allFrames ? InjectInAllFrames : InjectInTopFrameOnly); 
342 }
343
344 /**
345  * getPendingUnloadEventCount:
346  * @frame: a #WebKitWebFrame
347  *
348  * Return value: number of pending unload events
349  */
350 guint DumpRenderTreeSupportGtk::getPendingUnloadEventCount(WebKitWebFrame* frame)
351 {
352     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), 0);
353
354     return core(frame)->domWindow()->pendingUnloadEventListeners();
355 }
356
357 bool DumpRenderTreeSupportGtk::pauseAnimation(WebKitWebFrame* frame, const char* name, double time, const char* element)
358 {
359     ASSERT(core(frame));
360     Element* coreElement = core(frame)->document()->getElementById(AtomicString(element));
361     if (!coreElement || !coreElement->renderer())
362         return false;
363     return core(frame)->animation()->pauseAnimationAtTime(coreElement->renderer(), AtomicString(name), time);
364 }
365
366 bool DumpRenderTreeSupportGtk::pauseTransition(WebKitWebFrame* frame, const char* name, double time, const char* element)
367 {
368     ASSERT(core(frame));
369     Element* coreElement = core(frame)->document()->getElementById(AtomicString(element));
370     if (!coreElement || !coreElement->renderer())
371         return false;
372     return core(frame)->animation()->pauseTransitionAtTime(coreElement->renderer(), AtomicString(name), time);
373 }
374
375 bool DumpRenderTreeSupportGtk::pauseSVGAnimation(WebKitWebFrame* frame, const char* animationId, double time, const char* elementId)
376 {
377     ASSERT(core(frame));
378 #if ENABLE(SVG)
379     Document* document = core(frame)->document();
380     if (!document || !document->svgExtensions())
381         return false;
382     Element* coreElement = document->getElementById(AtomicString(animationId));
383     if (!coreElement || !SVGSMILElement::isSMILElement(coreElement))
384         return false;
385     return document->accessSVGExtensions()->sampleAnimationAtTime(elementId, static_cast<SVGSMILElement*>(coreElement), time);
386 #else
387     return false;
388 #endif
389 }
390
391 CString DumpRenderTreeSupportGtk::markerTextForListItem(WebKitWebFrame* frame, JSContextRef context, JSValueRef nodeObject)
392 {
393     JSC::ExecState* exec = toJS(context);
394     Element* element = toElement(toJS(exec, nodeObject));
395     if (!element)
396         return CString();
397
398     return WebCore::markerTextForListItem(element).utf8();
399 }
400
401 unsigned int DumpRenderTreeSupportGtk::numberOfActiveAnimations(WebKitWebFrame* frame)
402 {
403     Frame* coreFrame = core(frame);
404     if (!coreFrame)
405         return 0;
406
407     return coreFrame->animation()->numberOfActiveAnimations();
408 }
409
410 void DumpRenderTreeSupportGtk::suspendAnimations(WebKitWebFrame* frame)
411 {
412     Frame* coreFrame = core(frame);
413     if (!coreFrame)
414         return;
415
416     return coreFrame->animation()->suspendAnimations();
417 }
418
419 void DumpRenderTreeSupportGtk::resumeAnimations(WebKitWebFrame* frame)
420 {
421     Frame* coreFrame = core(frame);
422     if (!coreFrame)
423         return;
424
425     return coreFrame->animation()->resumeAnimations();
426 }
427
428 void DumpRenderTreeSupportGtk::clearMainFrameName(WebKitWebFrame* frame)
429 {
430     g_return_if_fail(WEBKIT_IS_WEB_FRAME(frame));
431
432     core(frame)->tree()->clearName();
433 }
434
435 AtkObject* DumpRenderTreeSupportGtk::getRootAccessibleElement(WebKitWebFrame* frame)
436 {
437     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), 0);
438
439 #if HAVE(ACCESSIBILITY)
440     if (!AXObjectCache::accessibilityEnabled())
441         AXObjectCache::enableAccessibility();
442
443     WebKitWebFramePrivate* priv = frame->priv;
444     if (!priv->coreFrame || !priv->coreFrame->document())
445         return 0;
446
447     AtkObject* wrapper =  priv->coreFrame->document()->axObjectCache()->rootObject()->wrapper();
448     if (!wrapper)
449         return 0;
450
451     return wrapper;
452 #else
453     return 0;
454 #endif
455 }
456
457 AtkObject* DumpRenderTreeSupportGtk::getFocusedAccessibleElement(WebKitWebFrame* frame)
458 {
459 #if HAVE(ACCESSIBILITY)
460     AtkObject* wrapper = getRootAccessibleElement(frame);
461     if (!wrapper)
462         return 0;
463
464     return webkit_accessible_get_focused_element(WEBKIT_ACCESSIBLE(wrapper));
465 #else
466     return 0;
467 #endif
468 }
469
470 void DumpRenderTreeSupportGtk::executeCoreCommandByName(WebKitWebView* webView, const gchar* name, const gchar* value)
471 {
472     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
473     g_return_if_fail(name);
474     g_return_if_fail(value);
475
476     core(webView)->focusController()->focusedOrMainFrame()->editor()->command(name).execute(value);
477 }
478
479 bool DumpRenderTreeSupportGtk::isCommandEnabled(WebKitWebView* webView, const gchar* name)
480 {
481     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
482     g_return_val_if_fail(name, FALSE);
483
484     return core(webView)->focusController()->focusedOrMainFrame()->editor()->command(name).isEnabled();
485 }
486
487 void DumpRenderTreeSupportGtk::setComposition(WebKitWebView* webView, const char* text, int start, int end)
488 {
489     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
490     g_return_if_fail(text);
491
492     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
493     if (!frame)
494         return;
495
496     Editor* editor = frame->editor();
497     if (!editor)
498         return;
499     if (!editor->canEdit() && !editor->hasComposition())
500         return;
501
502     String compositionString = String::fromUTF8(text);
503     Vector<CompositionUnderline> underlines;
504     underlines.append(CompositionUnderline(0, compositionString.length(), Color(0, 0, 0), false));
505     editor->setComposition(compositionString, underlines, start, end);
506 }
507
508 void DumpRenderTreeSupportGtk::confirmComposition(WebKitWebView* webView, const char* text)
509 {
510     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
511
512     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
513     if (!frame)
514         return;
515
516     Editor* editor = frame->editor();
517     if (!editor || (!editor->hasComposition() && !text))
518         return;
519
520     if (editor->hasComposition()) {
521         if (text)
522             editor->confirmComposition(String::fromUTF8(text));
523         else
524             editor->confirmComposition();
525     } else
526         editor->insertText(String::fromUTF8(text), 0);
527 }
528
529 bool DumpRenderTreeSupportGtk::firstRectForCharacterRange(WebKitWebView* webView, int location, int length, GdkRectangle* rect)
530 {
531     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), false);
532     g_return_val_if_fail(rect, false);
533
534     if ((location + length < location) && (location + length))
535         length = 0;
536
537     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
538     if (!frame)
539         return false;
540
541     Editor* editor = frame->editor();
542     if (!editor)
543         return false;
544
545     Element* selectionRoot = frame->selection()->rootEditableElement();
546     Element* scope = selectionRoot ? selectionRoot : frame->document()->documentElement();
547     RefPtr<Range> range = TextIterator::rangeFromLocationAndLength(scope, location, length);
548     if (!range)
549         return false;
550
551     *rect = editor->firstRectForRange(range.get());
552
553     return true;
554 }
555
556 bool DumpRenderTreeSupportGtk::selectedRange(WebKitWebView* webView, int* start, int* end)
557 {
558     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), false);
559     g_return_val_if_fail(start, false);
560     g_return_val_if_fail(end, false);
561
562     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
563     if (!frame)
564         return false;
565
566     RefPtr<Range> range = frame->selection()->toNormalizedRange().get();
567
568     Element* selectionRoot = frame->selection()->rootEditableElement();
569     Element* scope = selectionRoot ? selectionRoot : frame->document()->documentElement();
570
571     RefPtr<Range> testRange = Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset());
572     ASSERT(testRange->startContainer() == scope);
573     *start = TextIterator::rangeLength(testRange.get());
574
575     ExceptionCode ec;
576     testRange->setEnd(range->endContainer(), range->endOffset(), ec);
577     ASSERT(testRange->startContainer() == scope);
578     *end = TextIterator::rangeLength(testRange.get());
579
580     return true;
581 }
582
583 void DumpRenderTreeSupportGtk::whiteListAccessFromOrigin(const gchar* sourceOrigin, const gchar* destinationProtocol, const gchar* destinationHost, bool allowDestinationSubdomains)
584 {
585     SecurityOrigin::addOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains);
586 }
587
588 void DumpRenderTreeSupportGtk::resetOriginAccessWhiteLists()
589 {
590     SecurityOrigin::resetOriginAccessWhitelists();
591 }
592
593 void DumpRenderTreeSupportGtk::gcCollectJavascriptObjects()
594 {
595     gcController().garbageCollectNow();
596 }
597
598 void DumpRenderTreeSupportGtk::gcCollectJavascriptObjectsOnAlternateThread(bool waitUntilDone)
599 {
600     gcController().garbageCollectOnAlternateThreadForDebugging(waitUntilDone);
601 }
602
603 unsigned long DumpRenderTreeSupportGtk::gcCountJavascriptObjects()
604 {
605     JSC::JSLock lock(JSC::SilenceAssertionsOnly);
606     return JSDOMWindow::commonJSGlobalData()->heap.objectCount();
607 }
608
609 void DumpRenderTreeSupportGtk::layoutFrame(WebKitWebFrame* frame)
610 {
611     Frame* coreFrame = core(frame);
612     if (!coreFrame)
613         return;
614
615     FrameView* view = coreFrame->view();
616     if (!view)
617         return;
618
619     view->layout();
620 }
621
622 // For testing fast/viewport.
623 void DumpRenderTreeSupportGtk::dumpConfigurationForViewport(WebKitWebView* webView, gint deviceDPI, gint deviceWidth, gint deviceHeight, gint availableWidth, gint availableHeight)
624 {
625     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
626
627     ViewportArguments arguments = webView->priv->corePage->mainFrame()->document()->viewportArguments();
628     ViewportAttributes attrs = computeViewportAttributes(arguments, /* default layout width for non-mobile pages */ 980, deviceWidth, deviceHeight, deviceDPI, IntSize(availableWidth, availableHeight));
629
630     fprintf(stdout, "viewport size %dx%d scale %f with limits [%f, %f] and userScalable %f\n", attrs.layoutSize.width(), attrs.layoutSize.height(), attrs.initialScale, attrs.minimumScale, attrs.maximumScale, attrs.userScalable);
631 }
632
633 void DumpRenderTreeSupportGtk::clearOpener(WebKitWebFrame* frame)
634 {
635     Frame* coreFrame = core(frame);
636     if (coreFrame)
637         coreFrame->loader()->setOpener(0);
638 }
639
640 JSValueRef DumpRenderTreeSupportGtk::shadowRoot(JSContextRef context, JSValueRef value)
641 {
642     JSC::ExecState* exec = toJS(context);
643     Element* element = toElement(toJS(exec, value));
644     if (!element)
645       return JSValueMakeNull(context);
646
647     return toRef(exec, toJS(exec, element->shadowRoot()));
648 }
649
650 unsigned int DumpRenderTreeSupportGtk::workerThreadCount()
651 {
652 #if ENABLE(WORKERS)
653     return WebCore::WorkerThread::workerThreadCount();
654 #else
655     return 0;
656 #endif
657 }
658
659 bool DumpRenderTreeSupportGtk::webkitWebFrameSelectionHasSpellingMarker(WebKitWebFrame *frame, gint from, gint length)
660 {
661     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), FALSE);
662
663     return core(frame)->editor()->selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
664 }
665
666 bool DumpRenderTreeSupportGtk::findString(WebKitWebView* webView, const gchar* targetString, WebKitFindOptions findOptions)
667 {
668     return core(webView)->findString(String::fromUTF8(targetString), findOptions);
669 }
670
671 double DumpRenderTreeSupportGtk::defaultMinimumTimerInterval()
672 {
673     return Settings::defaultMinDOMTimerInterval();
674 }
675
676 void DumpRenderTreeSupportGtk::setMinimumTimerInterval(WebKitWebView* webView, double interval)
677 {
678     core(webView)->settings()->setMinDOMTimerInterval(interval);
679 }
680
681 void DumpRenderTreeSupportGtk::setAutofilled(JSContextRef context, JSValueRef nodeObject, bool autofilled)
682 {
683     JSC::ExecState* exec = toJS(context);
684     Element* element = toElement(toJS(exec, nodeObject));
685     if (!element)
686         return;
687     InputElement* inputElement = element->toInputElement();
688     if (!inputElement)
689         return;
690
691     static_cast<HTMLInputElement*>(inputElement)->setAutofilled(autofilled);
692 }
693
694 void DumpRenderTreeSupportGtk::setValueForUser(JSContextRef context, JSValueRef nodeObject, JSStringRef value)
695 {
696     JSC::ExecState* exec = toJS(context);
697     Element* element = toElement(toJS(exec, nodeObject));
698     if (!element)
699         return;
700     InputElement* inputElement = element->toInputElement();
701     if (!inputElement)
702         return;
703
704     size_t bufferSize = JSStringGetMaximumUTF8CStringSize(value);
705     GOwnPtr<gchar> valueBuffer(static_cast<gchar*>(g_malloc(bufferSize)));
706     JSStringGetUTF8CString(value, valueBuffer.get(), bufferSize);
707     inputElement->setValueForUser(String::fromUTF8(valueBuffer.get()));
708 }