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