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