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