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