Add DeviceController base-class to remove duplication of DeviceXXXControler
[WebKit-https.git] / Source / WebKit / qt / WebCoreSupport / DumpRenderTreeSupportQt.cpp
1 /*
2     Copyright (C) 2010 Robert Hogan <robert@roberthogan.net>
3     Copyright (C) 2008,2009,2010 Nokia Corporation and/or its subsidiary(-ies)
4     Copyright (C) 2007 Staikos Computing Services Inc.
5     Copyright (C) 2007, 2012 Apple Inc.
6
7     This library is free software; you can redistribute it and/or
8     modify it under the terms of the GNU Library 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     Library General Public License for more details.
16
17     You should have received a copy of the GNU Library General Public License
18     along with this library; see the file COPYING.LIB.  If not, write to
19     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20     Boston, MA 02110-1301, USA.
21 */
22
23 #include "config.h"
24 #include "DumpRenderTreeSupportQt.h"
25
26 #include "APICast.h"
27 #include "ApplicationCacheStorage.h"
28 #include "CSSComputedStyleDeclaration.h"
29 #include "ChromeClientQt.h"
30 #include "ContainerNode.h"
31 #include "ContextMenu.h"
32 #include "ContextMenuClientQt.h"
33 #include "ContextMenuController.h"
34 #include "DeviceOrientationClientMock.h"
35 #include "DeviceOrientationController.h"
36 #include "DeviceOrientationData.h"
37 #include "DocumentLoader.h"
38 #include "Editor.h"
39 #include "EditorClientQt.h"
40 #include "Element.h"
41 #include "FocusController.h"
42 #include "Frame.h"
43 #include "FrameLoaderClientQt.h"
44 #include "FrameView.h"
45 #include "GCController.h"
46 #include "JSNode.h"
47 #include "qt_runtime.h"
48 #include "GeolocationClient.h"
49 #include "GeolocationClientMock.h"
50 #include "GeolocationController.h"
51 #include "GeolocationError.h"
52 #include "GeolocationPosition.h"
53 #include "HTMLFormElement.h"
54 #include "HTMLInputElement.h"
55 #include "HistoryItem.h"
56 #include "InitWebCoreQt.h"
57 #include "InspectorController.h"
58 #include "NodeList.h"
59 #include "NotificationPresenterClientQt.h"
60 #include "Page.h"
61 #include "PageGroup.h"
62 #include "PluginDatabase.h"
63 #include "PluginView.h"
64 #include "PositionError.h"
65 #include "PrintContext.h"
66 #include "RenderListItem.h"
67 #include "RenderTreeAsText.h"
68 #include "SchemeRegistry.h"
69 #include "ScriptController.h"
70 #include "ScriptSourceCode.h"
71 #include "ScriptValue.h"
72 #include "SecurityOrigin.h"
73 #include "SecurityPolicy.h"
74 #include "Settings.h"
75 #include "TextIterator.h"
76 #include "ThirdPartyCookiesQt.h"
77 #include "WebCoreTestSupport.h"
78 #include "WorkerThread.h"
79 #include <wtf/CurrentTime.h>
80
81 #include "qwebelement.h"
82 #include "qwebframe.h"
83 #include "qwebframe_p.h"
84 #include "qwebhistory.h"
85 #include "qwebhistory_p.h"
86 #include "qwebpage.h"
87 #include "qwebpage_p.h"
88 #include "qwebscriptworld.h"
89
90 #if ENABLE(VIDEO) && USE(QT_MULTIMEDIA)
91 #include "HTMLVideoElement.h"
92 #include "MediaPlayerPrivateQt.h"
93 #endif
94
95 #include <QAction>
96 #include <QMenu>
97 #include <QPainter>
98
99 using namespace WebCore;
100
101 QMap<int, QWebScriptWorld*> m_worldMap;
102
103 #if ENABLE(GEOLOCATION)
104 GeolocationClientMock* toGeolocationClientMock(GeolocationClient* client)
105 {
106      ASSERT(QWebPagePrivate::drtRun);
107      return static_cast<GeolocationClientMock*>(client);
108 }
109 #endif
110
111 #if ENABLE(DEVICE_ORIENTATION)
112 DeviceOrientationClientMock* toDeviceOrientationClientMock(DeviceOrientationClient* client)
113 {
114     ASSERT(QWebPagePrivate::drtRun);
115     return static_cast<DeviceOrientationClientMock*>(client);
116 }
117 #endif
118
119 QDRTNode::QDRTNode()
120     : m_node(0)
121 {
122 }
123
124 QDRTNode::QDRTNode(WebCore::Node* node)
125     : m_node(0)
126 {
127     if (node) {
128         m_node = node;
129         m_node->ref();
130     }
131 }
132
133 QDRTNode::~QDRTNode()
134 {
135     if (m_node)
136         m_node->deref();
137 }
138
139 QDRTNode::QDRTNode(const QDRTNode& other)
140     :m_node(other.m_node)
141 {
142     if (m_node)
143         m_node->ref();
144 }
145
146 QDRTNode& QDRTNode::operator=(const QDRTNode& other)
147 {
148     if (this != &other) {
149         Node* otherNode = other.m_node;
150         if (otherNode)
151             otherNode->ref();
152         if (m_node)
153             m_node->deref();
154         m_node = otherNode;
155     }
156     return *this;
157 }
158
159 QDRTNode QtDRTNodeRuntime::create(WebCore::Node* node)
160 {
161     return QDRTNode(node);
162 }
163
164 WebCore::Node* QtDRTNodeRuntime::get(const QDRTNode& node)
165 {
166     return node.m_node;
167 }
168
169 static QVariant convertJSValueToNodeVariant(JSC::JSObject* object, int *distance, HashSet<JSObjectRef>*)
170 {
171     if (!object || !object->inherits(&JSNode::s_info))
172         return QVariant();
173     return QVariant::fromValue<QDRTNode>(QtDRTNodeRuntime::create((static_cast<JSNode*>(object))->impl()));
174 }
175
176 static JSC::JSValue convertNodeVariantToJSValue(JSC::ExecState* exec, WebCore::JSDOMGlobalObject* globalObject, const QVariant& variant)
177 {
178     return toJS(exec, globalObject, QtDRTNodeRuntime::get(variant.value<QDRTNode>()));
179 }
180
181 void QtDRTNodeRuntime::initialize()
182 {
183     static bool initialized = false;
184     if (initialized)
185         return;
186     initialized = true;
187     int id = qRegisterMetaType<QDRTNode>();
188     JSC::Bindings::registerCustomType(id, convertJSValueToNodeVariant, convertNodeVariantToJSValue);
189 }
190
191 DumpRenderTreeSupportQt::DumpRenderTreeSupportQt()
192 {
193 }
194
195 DumpRenderTreeSupportQt::~DumpRenderTreeSupportQt()
196 {
197 }
198
199 void DumpRenderTreeSupportQt::initialize()
200 {
201     WebCore::initializeWebCoreQt();
202     QtDRTNodeRuntime::initialize();
203 }
204
205 void DumpRenderTreeSupportQt::overwritePluginDirectories()
206 {
207     PluginDatabase* db = PluginDatabase::installedPlugins(/* populate */ false);
208
209     Vector<String> paths;
210     String qtPath(qgetenv("QTWEBKIT_PLUGIN_PATH").data());
211     qtPath.split(UChar(':'), /* allowEmptyEntries */ false, paths);
212
213     db->setPluginDirectories(paths);
214     db->refresh();
215 }
216
217 int DumpRenderTreeSupportQt::workerThreadCount()
218 {
219 #if ENABLE(WORKERS)
220     return WebCore::WorkerThread::workerThreadCount();
221 #else
222     return 0;
223 #endif
224 }
225
226 void DumpRenderTreeSupportQt::setDumpRenderTreeModeEnabled(bool b)
227 {
228     QWebPagePrivate::drtRun = b;
229 #if ENABLE(NETSCAPE_PLUGIN_API) && defined(XP_UNIX)
230     // PluginViewQt (X11) needs a few workarounds when running under DRT
231     PluginView::setIsRunningUnderDRT(b);
232 #endif
233 }
234
235 void DumpRenderTreeSupportQt::setFrameFlatteningEnabled(QWebPage* page, bool enabled)
236 {
237     QWebPagePrivate::core(page)->settings()->setFrameFlatteningEnabled(enabled);
238 }
239
240 void DumpRenderTreeSupportQt::webPageSetGroupName(QWebPage* page, const QString& groupName)
241 {
242     page->handle()->page->setGroupName(groupName);
243 }
244
245 QString DumpRenderTreeSupportQt::webPageGroupName(QWebPage* page)
246 {
247     return page->handle()->page->groupName();
248 }
249
250 void DumpRenderTreeSupportQt::webInspectorExecuteScript(QWebPage* page, long callId, const QString& script)
251 {
252 #if ENABLE(INSPECTOR)
253     if (!page->handle()->page->inspectorController())
254         return;
255     page->handle()->page->inspectorController()->evaluateForTestInFrontend(callId, script);
256 #endif
257 }
258
259 void DumpRenderTreeSupportQt::webInspectorClose(QWebPage* page)
260 {
261 #if ENABLE(INSPECTOR)
262     if (!page->handle()->page->inspectorController())
263         return;
264     page->handle()->page->inspectorController()->close();
265 #endif
266 }
267
268 void DumpRenderTreeSupportQt::webInspectorShow(QWebPage* page)
269 {
270 #if ENABLE(INSPECTOR)
271     if (!page->handle()->page->inspectorController())
272         return;
273     page->handle()->page->inspectorController()->show();
274 #endif
275 }
276
277 bool DumpRenderTreeSupportQt::hasDocumentElement(QWebFrame* frame)
278 {
279     return QWebFramePrivate::core(frame)->document()->documentElement();
280 }
281
282 void DumpRenderTreeSupportQt::setAutofilled(const QWebElement& element, bool isAutofilled)
283 {
284     WebCore::Element* webElement = element.m_element;
285     if (!webElement)
286         return;
287     HTMLInputElement* inputElement = webElement->toInputElement();
288     if (!inputElement)
289         return;
290
291     inputElement->setAutofilled(isAutofilled);
292 }
293
294 void DumpRenderTreeSupportQt::setValueForUser(const QWebElement& element, const QString& value)
295 {
296     WebCore::Element* webElement = element.m_element;
297     if (!webElement)
298         return;
299     HTMLInputElement* inputElement = webElement->toInputElement();
300     if (!inputElement)
301         return;
302
303     inputElement->setValueForUser(value);
304 }
305
306 // Pause a given CSS animation or transition on the target node at a specific time.
307 // If the animation or transition is already paused, it will update its pause time.
308 // This method is only intended to be used for testing the CSS animation and transition system.
309 bool DumpRenderTreeSupportQt::pauseAnimation(QWebFrame *frame, const QString &animationName, double time, const QString &elementId)
310 {
311     Frame* coreFrame = QWebFramePrivate::core(frame);
312     if (!coreFrame)
313         return false;
314
315     AnimationController* controller = coreFrame->animation();
316     if (!controller)
317         return false;
318
319     Document* doc = coreFrame->document();
320     Q_ASSERT(doc);
321
322     Node* coreNode = doc->getElementById(elementId);
323     if (!coreNode || !coreNode->renderer())
324         return false;
325
326     return controller->pauseAnimationAtTime(coreNode->renderer(), animationName, time);
327 }
328
329 bool DumpRenderTreeSupportQt::pauseTransitionOfProperty(QWebFrame *frame, const QString &propertyName, double time, const QString &elementId)
330 {
331     Frame* coreFrame = QWebFramePrivate::core(frame);
332     if (!coreFrame)
333         return false;
334
335     AnimationController* controller = coreFrame->animation();
336     if (!controller)
337         return false;
338
339     Document* doc = coreFrame->document();
340     Q_ASSERT(doc);
341
342     Node* coreNode = doc->getElementById(elementId);
343     if (!coreNode || !coreNode->renderer())
344         return false;
345
346     return controller->pauseTransitionAtTime(coreNode->renderer(), propertyName, time);
347 }
348
349 // Returns the total number of currently running animations (includes both CSS transitions and CSS animations).
350 int DumpRenderTreeSupportQt::numberOfActiveAnimations(QWebFrame *frame)
351 {
352     Frame* coreFrame = QWebFramePrivate::core(frame);
353     if (!coreFrame)
354         return false;
355
356     AnimationController* controller = coreFrame->animation();
357     if (!controller)
358         return false;
359
360     return controller->numberOfActiveAnimations(coreFrame->document());
361 }
362
363 void DumpRenderTreeSupportQt::clearFrameName(QWebFrame* frame)
364 {
365     Frame* coreFrame = QWebFramePrivate::core(frame);
366     coreFrame->tree()->clearName();
367 }
368
369 int DumpRenderTreeSupportQt::javaScriptObjectsCount()
370 {
371     return JSDOMWindowBase::commonJSGlobalData()->heap.globalObjectCount();
372 }
373
374 void DumpRenderTreeSupportQt::garbageCollectorCollect()
375 {
376     gcController().garbageCollectNow();
377 }
378
379 void DumpRenderTreeSupportQt::garbageCollectorCollectOnAlternateThread(bool waitUntilDone)
380 {
381     gcController().garbageCollectOnAlternateThreadForDebugging(waitUntilDone);
382 }
383
384 // Suspend active DOM objects in this frame.
385 void DumpRenderTreeSupportQt::suspendActiveDOMObjects(QWebFrame* frame)
386 {
387     Frame* coreFrame = QWebFramePrivate::core(frame);
388     if (coreFrame->document())
389         // FIXME: This function should be changed take a ReasonForSuspension parameter 
390         // https://bugs.webkit.org/show_bug.cgi?id=45732
391         coreFrame->document()->suspendActiveDOMObjects(ActiveDOMObject::JavaScriptDebuggerPaused);
392 }
393
394 // Resume active DOM objects in this frame.
395 void DumpRenderTreeSupportQt::resumeActiveDOMObjects(QWebFrame* frame)
396 {
397     Frame* coreFrame = QWebFramePrivate::core(frame);
398     if (coreFrame->document())
399         coreFrame->document()->resumeActiveDOMObjects();
400 }
401
402 void DumpRenderTreeSupportQt::whiteListAccessFromOrigin(const QString& sourceOrigin, const QString& destinationProtocol, const QString& destinationHost, bool allowDestinationSubdomains)
403 {
404     SecurityPolicy::addOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains);
405 }
406
407 void DumpRenderTreeSupportQt::removeWhiteListAccessFromOrigin(const QString& sourceOrigin, const QString& destinationProtocol, const QString& destinationHost, bool allowDestinationSubdomains)
408 {
409     SecurityPolicy::removeOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains);
410 }
411
412 void DumpRenderTreeSupportQt::resetOriginAccessWhiteLists()
413 {
414     SecurityPolicy::resetOriginAccessWhitelists();
415 }
416
417 void DumpRenderTreeSupportQt::setDomainRelaxationForbiddenForURLScheme(bool forbidden, const QString& scheme)
418 {
419     SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(forbidden, scheme);
420 }
421
422 void DumpRenderTreeSupportQt::setCaretBrowsingEnabled(QWebPage* page, bool value)
423 {
424     page->handle()->page->settings()->setCaretBrowsingEnabled(value);
425 }
426
427 void DumpRenderTreeSupportQt::setAuthorAndUserStylesEnabled(QWebPage* page, bool value)
428 {
429     page->handle()->page->settings()->setAuthorAndUserStylesEnabled(value);
430 }
431
432 void DumpRenderTreeSupportQt::setSmartInsertDeleteEnabled(QWebPage* page, bool enabled)
433 {
434     page->d->smartInsertDeleteEnabled = enabled;
435 }
436
437
438 void DumpRenderTreeSupportQt::setSelectTrailingWhitespaceEnabled(QWebPage* page, bool enabled)
439 {
440     page->d->selectTrailingWhitespaceEnabled = enabled;
441 }
442
443
444 void DumpRenderTreeSupportQt::executeCoreCommandByName(QWebPage* page, const QString& name, const QString& value)
445 {
446     page->handle()->page->focusController()->focusedOrMainFrame()->editor()->command(name).execute(value);
447 }
448
449 bool DumpRenderTreeSupportQt::isCommandEnabled(QWebPage* page, const QString& name)
450 {
451     return page->handle()->page->focusController()->focusedOrMainFrame()->editor()->command(name).isEnabled();
452 }
453
454 bool DumpRenderTreeSupportQt::findString(QWebPage* page, const QString& string, const QStringList& optionArray)
455 {
456     // 1. Parse the options from the array
457     WebCore::FindOptions options = 0;
458     const int optionCount = optionArray.size();
459     for (int i = 0; i < optionCount; ++i) {
460         const QString& option = optionArray.at(i);
461         if (option == QLatin1String("CaseInsensitive"))
462             options |= WebCore::CaseInsensitive;
463         else if (option == QLatin1String("AtWordStarts"))
464             options |= WebCore::AtWordStarts;
465         else if (option == QLatin1String("TreatMedialCapitalAsWordStart"))
466             options |= WebCore::TreatMedialCapitalAsWordStart;
467         else if (option == QLatin1String("Backwards"))
468             options |= WebCore::Backwards;
469         else if (option == QLatin1String("WrapAround"))
470             options |= WebCore::WrapAround;
471         else if (option == QLatin1String("StartInSelection"))
472             options |= WebCore::StartInSelection;
473     }
474
475     // 2. find the string
476     WebCore::Frame* frame = page->handle()->page->focusController()->focusedOrMainFrame();
477     return frame && frame->editor()->findString(string, options);
478 }
479
480 QString DumpRenderTreeSupportQt::markerTextForListItem(const QWebElement& listItem)
481 {
482     return WebCore::markerTextForListItem(listItem.m_element);
483 }
484
485 static QString convertToPropertyName(const QString& name)
486 {
487     QStringList parts = name.split(QLatin1Char('-'));
488     QString camelCaseName;
489     for (int j = 0; j < parts.count(); ++j) {
490         QString part = parts.at(j);
491         if (j)
492             camelCaseName.append(part.replace(0, 1, part.left(1).toUpper()));
493         else
494             camelCaseName.append(part);
495     }
496     return camelCaseName;
497 }
498
499 QVariantMap DumpRenderTreeSupportQt::computedStyleIncludingVisitedInfo(const QWebElement& element)
500 {
501     QVariantMap res;
502
503     WebCore::Element* webElement = element.m_element;
504     if (!webElement)
505         return res;
506
507     RefPtr<WebCore::CSSComputedStyleDeclaration> computedStyleDeclaration = CSSComputedStyleDeclaration::create(webElement, true);
508     CSSStyleDeclaration* style = static_cast<WebCore::CSSStyleDeclaration*>(computedStyleDeclaration.get());
509     for (unsigned i = 0; i < style->length(); i++) {
510         QString name = style->item(i);
511         QString value = style->getPropertyValue(name);
512         res[convertToPropertyName(name)] = QVariant(value);
513     }
514     return res;
515 }
516
517 QVariantList DumpRenderTreeSupportQt::selectedRange(QWebPage* page)
518 {
519     WebCore::Frame* frame = page->handle()->page->focusController()->focusedOrMainFrame();
520     QVariantList selectedRange;
521     RefPtr<Range> range = frame->selection()->toNormalizedRange().get();
522
523     Element* selectionRoot = frame->selection()->rootEditableElement();
524     Element* scope = selectionRoot ? selectionRoot : frame->document()->documentElement();
525
526     RefPtr<Range> testRange = Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset());
527     ASSERT(testRange->startContainer() == scope);
528     int startPosition = TextIterator::rangeLength(testRange.get());
529
530     ExceptionCode ec;
531     testRange->setEnd(range->endContainer(), range->endOffset(), ec);
532     ASSERT(testRange->startContainer() == scope);
533     int endPosition = TextIterator::rangeLength(testRange.get());
534
535     selectedRange << startPosition << (endPosition - startPosition);
536
537     return selectedRange;
538
539 }
540
541 QVariantList DumpRenderTreeSupportQt::firstRectForCharacterRange(QWebPage* page, int location, int length)
542 {
543     WebCore::Frame* frame = page->handle()->page->focusController()->focusedOrMainFrame();
544     QVariantList rect;
545
546     if ((location + length < location) && (location + length))
547         length = 0;
548
549     RefPtr<Range> range = TextIterator::rangeFromLocationAndLength(frame->selection()->rootEditableElementOrDocumentElement(), location, length);
550
551     if (!range)
552         return QVariantList();
553
554     QRect resultRect = frame->editor()->firstRectForRange(range.get());
555     rect << resultRect.x() << resultRect.y() << resultRect.width() << resultRect.height();
556     return rect;
557 }
558
559 bool DumpRenderTreeSupportQt::elementDoesAutoCompleteForElementWithId(QWebFrame* frame, const QString& elementId)
560 {
561     Frame* coreFrame = QWebFramePrivate::core(frame);
562     if (!coreFrame)
563         return false;
564
565     Document* doc = coreFrame->document();
566     Q_ASSERT(doc);
567
568     Node* coreNode = doc->getElementById(elementId);
569     if (!coreNode || !coreNode->renderer())
570         return false;
571
572     HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(coreNode);
573
574     return inputElement->isTextField() && !inputElement->isPasswordField() && inputElement->shouldAutocomplete();
575 }
576
577 void DumpRenderTreeSupportQt::setWindowsBehaviorAsEditingBehavior(QWebPage* page)
578 {
579     Page* corePage = QWebPagePrivate::core(page);
580     if (!corePage)
581         return;
582     corePage->settings()->setEditingBehaviorType(EditingWindowsBehavior);
583 }
584
585 void DumpRenderTreeSupportQt::clearAllApplicationCaches()
586 {
587     WebCore::cacheStorage().empty();
588     WebCore::cacheStorage().vacuumDatabaseFile();
589 }
590
591 void DumpRenderTreeSupportQt::dumpFrameLoader(bool b)
592 {
593     FrameLoaderClientQt::dumpFrameLoaderCallbacks = b;
594 }
595
596 void DumpRenderTreeSupportQt::dumpProgressFinishedCallback(bool b)
597 {
598     FrameLoaderClientQt::dumpProgressFinishedCallback = b;
599 }
600
601 void DumpRenderTreeSupportQt::dumpUserGestureInFrameLoader(bool b)
602 {
603     FrameLoaderClientQt::dumpUserGestureInFrameLoaderCallbacks = b;
604 }
605
606 void DumpRenderTreeSupportQt::dumpResourceLoadCallbacks(bool b)
607 {
608     FrameLoaderClientQt::dumpResourceLoadCallbacks = b;
609 }
610
611 void DumpRenderTreeSupportQt::dumpResourceLoadCallbacksPath(const QString& path)
612 {
613     FrameLoaderClientQt::dumpResourceLoadCallbacksPath = path;
614 }
615
616 void DumpRenderTreeSupportQt::dumpResourceResponseMIMETypes(bool b)
617 {
618     FrameLoaderClientQt::dumpResourceResponseMIMETypes = b;
619 }
620
621 void DumpRenderTreeSupportQt::dumpWillCacheResponseCallbacks(bool b)
622 {
623     FrameLoaderClientQt::dumpWillCacheResponseCallbacks = b;
624 }
625
626 void DumpRenderTreeSupportQt::setWillSendRequestReturnsNullOnRedirect(bool b)
627 {
628     FrameLoaderClientQt::sendRequestReturnsNullOnRedirect = b;
629 }
630
631 void DumpRenderTreeSupportQt::setWillSendRequestReturnsNull(bool b)
632 {
633     FrameLoaderClientQt::sendRequestReturnsNull = b;
634 }
635
636 void DumpRenderTreeSupportQt::setWillSendRequestClearHeaders(const QStringList& headers)
637 {
638     FrameLoaderClientQt::sendRequestClearHeaders = headers;
639 }
640
641 void DumpRenderTreeSupportQt::setDeferMainResourceDataLoad(bool b)
642 {
643     FrameLoaderClientQt::deferMainResourceDataLoad = b;
644 }
645
646 void DumpRenderTreeSupportQt::setCustomPolicyDelegate(bool enabled, bool permissive)
647 {
648     FrameLoaderClientQt::policyDelegateEnabled = enabled;
649     FrameLoaderClientQt::policyDelegatePermissive = permissive;
650 }
651
652 void DumpRenderTreeSupportQt::dumpHistoryCallbacks(bool b)
653 {
654     FrameLoaderClientQt::dumpHistoryCallbacks = b;
655 }
656
657 void DumpRenderTreeSupportQt::dumpVisitedLinksCallbacks(bool b)
658 {
659     ChromeClientQt::dumpVisitedLinksCallbacks = b;
660 }
661
662 void DumpRenderTreeSupportQt::dumpEditingCallbacks(bool b)
663 {
664     EditorClientQt::dumpEditingCallbacks = b;
665 }
666
667 void DumpRenderTreeSupportQt::dumpSetAcceptsEditing(bool b)
668 {
669     EditorClientQt::acceptsEditing = b;
670 }
671
672 void DumpRenderTreeSupportQt::dumpNotification(bool b)
673 {
674 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
675     NotificationPresenterClientQt::dumpNotification = b;
676 #endif
677 }
678
679 QString DumpRenderTreeSupportQt::viewportAsText(QWebPage* page, int deviceDPI, const QSize& deviceSize, const QSize& availableSize)
680 {
681     WebCore::ViewportArguments args = page->d->viewportArguments();
682
683     float devicePixelRatio = deviceDPI / WebCore::ViewportArguments::deprecatedTargetDPI;
684     WebCore::ViewportAttributes conf = WebCore::computeViewportAttributes(args,
685         /* desktop-width    */ 980,
686         /* device-width     */ deviceSize.width(),
687         /* device-height    */ deviceSize.height(),
688         devicePixelRatio,
689         availableSize);
690     WebCore::restrictMinimumScaleFactorToViewportSize(conf, availableSize, devicePixelRatio);
691     WebCore::restrictScaleFactorToInitialScaleIfNotUserScalable(conf);
692
693     QString res;
694     res = res.sprintf("viewport size %dx%d scale %f with limits [%f, %f] and userScalable %f\n",
695             static_cast<int>(conf.layoutSize.width()),
696             static_cast<int>(conf.layoutSize.height()),
697             conf.initialScale,
698             conf.minimumScale,
699             conf.maximumScale,
700             conf.userScalable);
701
702     return res;
703 }
704
705 void DumpRenderTreeSupportQt::scalePageBy(QWebFrame* frame, float scalefactor, const QPoint& origin)
706 {
707     WebCore::Frame* coreFrame = QWebFramePrivate::core(frame);
708     if (Page* page = coreFrame->page())
709         page->setPageScaleFactor(scalefactor, origin);
710 }
711
712 void DumpRenderTreeSupportQt::setMockDeviceOrientation(QWebPage* page, bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma)
713 {
714 #if ENABLE(DEVICE_ORIENTATION)
715     Page* corePage = QWebPagePrivate::core(page);
716     DeviceOrientationClientMock* mockClient = toDeviceOrientationClientMock(DeviceOrientationController::from(corePage)->deviceOrientationClient());
717     mockClient->setOrientation(DeviceOrientationData::create(canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma));
718 #endif
719 }
720
721 void DumpRenderTreeSupportQt::resetGeolocationMock(QWebPage* page)
722 {
723 #if ENABLE(GEOLOCATION)
724     Page* corePage = QWebPagePrivate::core(page);
725     GeolocationClientMock* mockClient = toGeolocationClientMock(GeolocationController::from(corePage)->client());
726     mockClient->reset();
727 #endif
728 }
729
730 void DumpRenderTreeSupportQt::setMockGeolocationPermission(QWebPage* page, bool allowed)
731 {
732 #if ENABLE(GEOLOCATION)
733     Page* corePage = QWebPagePrivate::core(page);
734     GeolocationClientMock* mockClient = toGeolocationClientMock(GeolocationController::from(corePage)->client());
735     mockClient->setPermission(allowed);
736 #endif
737 }
738
739 void DumpRenderTreeSupportQt::setMockGeolocationPosition(QWebPage* page, double latitude, double longitude, double accuracy)
740 {
741 #if ENABLE(GEOLOCATION)
742     Page* corePage = QWebPagePrivate::core(page);
743     GeolocationClientMock* mockClient = toGeolocationClientMock(GeolocationController::from(corePage)->client());
744     mockClient->setPosition(GeolocationPosition::create(currentTime(), latitude, longitude, accuracy));
745 #endif
746 }
747
748 void DumpRenderTreeSupportQt::setMockGeolocationPositionUnavailableError(QWebPage* page, const QString& message)
749 {
750 #if ENABLE(GEOLOCATION)
751     Page* corePage = QWebPagePrivate::core(page);
752     GeolocationClientMock* mockClient = static_cast<GeolocationClientMock*>(GeolocationController::from(corePage)->client());
753     mockClient->setPositionUnavailableError(message);
754 #endif
755 }
756
757 int DumpRenderTreeSupportQt::numberOfPendingGeolocationPermissionRequests(QWebPage* page)
758 {
759 #if ENABLE(GEOLOCATION)
760     Page* corePage = QWebPagePrivate::core(page);
761     GeolocationClientMock* mockClient = toGeolocationClientMock(GeolocationController::from(corePage)->client());
762     return mockClient->numberOfPendingPermissionRequests();
763 #else
764     return -1;
765 #endif
766 }
767
768 bool DumpRenderTreeSupportQt::isTargetItem(const QWebHistoryItem& historyItem)
769 {
770     QWebHistoryItem it = historyItem;
771     if (QWebHistoryItemPrivate::core(&it)->isTargetItem())
772         return true;
773     return false;
774 }
775
776 QString DumpRenderTreeSupportQt::historyItemTarget(const QWebHistoryItem& historyItem)
777 {
778     QWebHistoryItem it = historyItem;
779     return (QWebHistoryItemPrivate::core(&it)->target());
780 }
781
782 QMap<QString, QWebHistoryItem> DumpRenderTreeSupportQt::getChildHistoryItems(const QWebHistoryItem& historyItem)
783 {
784     QWebHistoryItem it = historyItem;
785     HistoryItem* item = QWebHistoryItemPrivate::core(&it);
786     const WebCore::HistoryItemVector& children = item->children();
787
788     unsigned size = children.size();
789     QMap<QString, QWebHistoryItem> kids;
790     for (unsigned i = 0; i < size; ++i) {
791         QWebHistoryItem kid(new QWebHistoryItemPrivate(children[i].get()));
792         kids.insert(DumpRenderTreeSupportQt::historyItemTarget(kid), kid);
793     }
794     return kids;
795 }
796
797 bool DumpRenderTreeSupportQt::shouldClose(QWebFrame* frame)
798 {
799     WebCore::Frame* coreFrame = QWebFramePrivate::core(frame);
800     return coreFrame->loader()->shouldClose();
801 }
802
803 void DumpRenderTreeSupportQt::clearScriptWorlds()
804 {
805     m_worldMap.clear();
806 }
807
808 void DumpRenderTreeSupportQt::evaluateScriptInIsolatedWorld(QWebFrame* frame, int worldID, const QString& script)
809 {
810     QWebScriptWorld* scriptWorld;
811     if (!worldID) {
812         scriptWorld = new QWebScriptWorld();
813     } else if (!m_worldMap.contains(worldID)) {
814         scriptWorld = new QWebScriptWorld();
815         m_worldMap.insert(worldID, scriptWorld);
816     } else
817         scriptWorld = m_worldMap.value(worldID);
818
819     WebCore::Frame* coreFrame = QWebFramePrivate::core(frame);
820
821     ScriptController* proxy = coreFrame->script();
822
823     if (!proxy)
824         return;
825     proxy->executeScriptInWorld(scriptWorld->world(), script, true);
826 }
827
828 void DumpRenderTreeSupportQt::addUserStyleSheet(QWebPage* page, const QString& sourceCode)
829 {
830     page->handle()->page->group().addUserStyleSheetToWorld(mainThreadNormalWorld(), sourceCode, QUrl(), Vector<String>(), Vector<String>(), WebCore::InjectInAllFrames);
831 }
832
833 void DumpRenderTreeSupportQt::removeUserStyleSheets(QWebPage* page)
834 {
835     page->handle()->page->group().removeUserStyleSheetsFromWorld(mainThreadNormalWorld());
836 }
837
838 void DumpRenderTreeSupportQt::simulateDesktopNotificationClick(const QString& title)
839 {
840 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
841     NotificationPresenterClientQt::notificationPresenter()->notificationClicked(title);
842 #endif
843 }
844
845 void DumpRenderTreeSupportQt::setDefersLoading(QWebPage* page, bool flag)
846 {
847     Page* corePage = QWebPagePrivate::core(page);
848     if (corePage)
849         corePage->setDefersLoading(flag);
850 }
851
852 void DumpRenderTreeSupportQt::goBack(QWebPage* page)
853 {
854     Page* corePage = QWebPagePrivate::core(page);
855     if (corePage)
856         corePage->goBack();
857 }
858
859 // API Candidate?
860 QString DumpRenderTreeSupportQt::responseMimeType(QWebFrame* frame)
861 {
862     WebCore::Frame* coreFrame = QWebFramePrivate::core(frame);
863     WebCore::DocumentLoader* docLoader = coreFrame->loader()->documentLoader();
864     return docLoader->responseMIMEType();
865 }
866
867 void DumpRenderTreeSupportQt::clearOpener(QWebFrame* frame)
868 {
869     WebCore::Frame* coreFrame = QWebFramePrivate::core(frame);
870     coreFrame->loader()->setOpener(0);
871 }
872
873 void DumpRenderTreeSupportQt::addURLToRedirect(const QString& origin, const QString& destination)
874 {
875     FrameLoaderClientQt::URLsToRedirect[origin] = destination;
876 }
877
878 void DumpRenderTreeSupportQt::setInteractiveFormValidationEnabled(QWebPage* page, bool enable)
879 {
880     Page* corePage = QWebPagePrivate::core(page);
881     if (corePage)
882         corePage->settings()->setInteractiveFormValidationEnabled(enable);
883 }
884
885 #ifndef QT_NO_MENU
886 static QStringList iterateContextMenu(QMenu* menu)
887 {
888     if (!menu)
889         return QStringList();
890
891     QStringList items;
892     QList<QAction *> actions = menu->actions();
893     for (int i = 0; i < actions.count(); ++i) {
894         if (actions.at(i)->isSeparator())
895             items << QLatin1String("<separator>");
896         else
897             items << actions.at(i)->text();
898         if (actions.at(i)->menu())
899             items << iterateContextMenu(actions.at(i)->menu());
900     }
901     return items;
902 }
903 #endif
904
905 QStringList DumpRenderTreeSupportQt::contextMenu(QWebPage* page)
906 {
907 #ifndef QT_NO_CONTEXTMENU
908     return iterateContextMenu(page->d->currentContextMenu.data());
909 #else
910     return QStringList();
911 #endif
912 }
913
914 double DumpRenderTreeSupportQt::defaultMinimumTimerInterval()
915 {
916     return Settings::defaultMinDOMTimerInterval();
917 }
918
919 void DumpRenderTreeSupportQt::setMinimumTimerInterval(QWebPage* page, double interval)
920 {
921     Page* corePage = QWebPagePrivate::core(page);
922     if (!corePage)
923         return;
924
925     corePage->settings()->setMinDOMTimerInterval(interval);
926 }
927
928 bool DumpRenderTreeSupportQt::thirdPartyCookiePolicyAllows(QWebPage *page, const QUrl& url, const QUrl& firstPartyUrl)
929 {
930     Page* corePage = QWebPagePrivate::core(page);
931     return thirdPartyCookiePolicyPermits(corePage->mainFrame()->loader()->networkingContext(), url, firstPartyUrl);
932 }
933
934 void DumpRenderTreeSupportQt::enableMockScrollbars()
935 {
936     Settings::setMockScrollbarsEnabled(true);
937 }
938
939 QUrl DumpRenderTreeSupportQt::mediaContentUrlByElementId(QWebFrame* frame, const QString& elementId)
940 {
941     QUrl res;
942
943 #if ENABLE(VIDEO) && USE(QT_MULTIMEDIA)
944     Frame* coreFrame = QWebFramePrivate::core(frame);
945     if (!coreFrame)
946         return res;
947
948     Document* doc = coreFrame->document();
949     if (!doc)
950         return res;
951
952     Node* coreNode = doc->getElementById(elementId);
953     if (!coreNode)
954         return res;
955
956     HTMLVideoElement* videoElement = static_cast<HTMLVideoElement*>(coreNode);
957     PlatformMedia platformMedia = videoElement->platformMedia();
958     if (platformMedia.type != PlatformMedia::QtMediaPlayerType)
959         return res;
960
961     MediaPlayerPrivateQt* mediaPlayerQt = static_cast<MediaPlayerPrivateQt*>(platformMedia.media.qtMediaPlayer);
962     if (mediaPlayerQt && mediaPlayerQt->mediaPlayer())
963         res = mediaPlayerQt->mediaPlayer()->media().canonicalUrl();
964 #endif
965
966     return res;
967 }
968
969 // API Candidate?
970 void DumpRenderTreeSupportQt::setAlternateHtml(QWebFrame* frame, const QString& html, const QUrl& baseUrl, const QUrl& failingUrl)
971 {
972     KURL kurl(baseUrl);
973     WebCore::Frame* coreFrame = QWebFramePrivate::core(frame);
974     WebCore::ResourceRequest request(kurl);
975     const QByteArray utf8 = html.toUtf8();
976     WTF::RefPtr<WebCore::SharedBuffer> data = WebCore::SharedBuffer::create(utf8.constData(), utf8.length());
977     WebCore::SubstituteData substituteData(data, WTF::String("text/html"), WTF::String("utf-8"), failingUrl);
978     coreFrame->loader()->load(request, substituteData, false);
979 }
980
981 void DumpRenderTreeSupportQt::confirmComposition(QWebPage* page, const char* text)
982 {
983     Frame* frame = page->handle()->page->focusController()->focusedOrMainFrame();
984     if (!frame)
985         return;
986
987     Editor* editor = frame->editor();
988     if (!editor || (!editor->hasComposition() && !text))
989         return;
990
991     if (editor->hasComposition()) {
992         if (text)
993             editor->confirmComposition(String::fromUTF8(text));
994         else
995             editor->confirmComposition();
996     } else
997         editor->insertText(String::fromUTF8(text), 0);
998 }
999
1000 QString DumpRenderTreeSupportQt::layerTreeAsText(QWebFrame* frame)
1001 {
1002     WebCore::Frame* coreFrame = QWebFramePrivate::core(frame);
1003     return coreFrame->layerTreeAsText();
1004 }
1005
1006 void DumpRenderTreeSupportQt::injectInternalsObject(QWebFrame* frame)
1007 {
1008     WebCore::Frame* coreFrame = QWebFramePrivate::core(frame);
1009     JSDOMWindow* window = toJSDOMWindow(coreFrame, mainThreadNormalWorld());
1010     Q_ASSERT(window);
1011
1012     JSC::ExecState* exec = window->globalExec();
1013     Q_ASSERT(exec);
1014     JSC::JSLockHolder lock(exec);
1015
1016     JSContextRef context = toRef(exec);
1017     WebCoreTestSupport::injectInternalsObject(context);
1018 }
1019
1020 void DumpRenderTreeSupportQt::injectInternalsObject(JSContextRef context)
1021 {
1022     WebCoreTestSupport::injectInternalsObject(context);
1023 }
1024
1025 void DumpRenderTreeSupportQt::resetInternalsObject(QWebFrame* frame)
1026 {
1027     WebCore::Frame* coreFrame = QWebFramePrivate::core(frame);
1028     JSDOMWindow* window = toJSDOMWindow(coreFrame, mainThreadNormalWorld());
1029     Q_ASSERT(window);
1030
1031     JSC::ExecState* exec = window->globalExec();
1032     Q_ASSERT(exec);
1033     JSC::JSLockHolder lock(exec);
1034
1035     JSContextRef context = toRef(exec);
1036     WebCoreTestSupport::resetInternalsObject(context);
1037 }
1038
1039 void DumpRenderTreeSupportQt::resetInternalsObject(JSContextRef context)
1040 {
1041     WebCoreTestSupport::resetInternalsObject(context);
1042 }
1043
1044 QImage DumpRenderTreeSupportQt::paintPagesWithBoundaries(QWebFrame* qframe)
1045 {
1046     Frame* frame = QWebFramePrivate::core(qframe);
1047     PrintContext printContext(frame);
1048
1049     QRect rect = frame->view()->frameRect();
1050
1051     IntRect pageRect(0, 0, rect.width(), rect.height());
1052
1053     printContext.begin(pageRect.width(), pageRect.height());
1054     float pageHeight = 0;
1055     printContext.computePageRects(pageRect, /* headerHeight */ 0, /* footerHeight */ 0, /* userScaleFactor */ 1.0, pageHeight);
1056
1057     QPainter painter;
1058     int pageCount = printContext.pageCount();
1059     // pages * pageHeight and 1px line between each page
1060     int totalHeight = pageCount * (pageRect.height() + 1) - 1;
1061     QImage image(pageRect.width(), totalHeight, QImage::Format_ARGB32);
1062     image.fill(Qt::white);
1063     painter.begin(&image);
1064
1065     GraphicsContext ctx(&painter);
1066     for (int i = 0; i < printContext.pageCount(); ++i) {
1067         printContext.spoolPage(ctx, i, pageRect.width());
1068         // translate to next page coordinates
1069         ctx.translate(0, pageRect.height() + 1);
1070
1071         // if there is a next page, draw a blue line between these two
1072         if (i + 1 < printContext.pageCount()) {
1073             ctx.save();
1074             ctx.setStrokeColor(Color(0, 0, 255), ColorSpaceDeviceRGB);
1075             ctx.setFillColor(Color(0, 0, 255), ColorSpaceDeviceRGB);
1076             ctx.drawLine(IntPoint(0, -1), IntPoint(pageRect.width(), -1));
1077             ctx.restore();
1078         }
1079     }
1080
1081     painter.end();
1082     printContext.end();
1083
1084     return image;
1085 }
1086
1087 void DumpRenderTreeSupportQt::setTrackRepaintRects(QWebFrame* frame, bool enable)
1088 {
1089     QWebFramePrivate::core(frame)->view()->setTracksRepaints(enable);
1090 }
1091
1092 bool DumpRenderTreeSupportQt::trackRepaintRects(QWebFrame* frame)
1093 {
1094     return QWebFramePrivate::core(frame)->view()->isTrackingRepaints();
1095 }
1096
1097 void DumpRenderTreeSupportQt::getTrackedRepaintRects(QWebFrame* frame, QVector<QRect>& result)
1098 {
1099     Frame* coreFrame = QWebFramePrivate::core(frame);
1100     const Vector<IntRect>& rects = coreFrame->view()->trackedRepaintRects();
1101     result.resize(rects.size());
1102     for (size_t i = 0; i < rects.size(); ++i)
1103         result.append(rects[i]);
1104 }
1105
1106 // Provide a backward compatibility with previously exported private symbols as of QtWebKit 4.6 release
1107
1108 void QWEBKIT_EXPORT qt_resumeActiveDOMObjects(QWebFrame* frame)
1109 {
1110     DumpRenderTreeSupportQt::resumeActiveDOMObjects(frame);
1111 }
1112
1113 void QWEBKIT_EXPORT qt_suspendActiveDOMObjects(QWebFrame* frame)
1114 {
1115     DumpRenderTreeSupportQt::suspendActiveDOMObjects(frame);
1116 }
1117
1118 void QWEBKIT_EXPORT qt_drt_clearFrameName(QWebFrame* frame)
1119 {
1120     DumpRenderTreeSupportQt::clearFrameName(frame);
1121 }
1122
1123 void QWEBKIT_EXPORT qt_drt_garbageCollector_collect()
1124 {
1125     DumpRenderTreeSupportQt::garbageCollectorCollect();
1126 }
1127
1128 void QWEBKIT_EXPORT qt_drt_garbageCollector_collectOnAlternateThread(bool waitUntilDone)
1129 {
1130     DumpRenderTreeSupportQt::garbageCollectorCollectOnAlternateThread(waitUntilDone);
1131 }
1132
1133 int QWEBKIT_EXPORT qt_drt_javaScriptObjectsCount()
1134 {
1135     return DumpRenderTreeSupportQt::javaScriptObjectsCount();
1136 }
1137
1138 int QWEBKIT_EXPORT qt_drt_numberOfActiveAnimations(QWebFrame* frame)
1139 {
1140     return DumpRenderTreeSupportQt::numberOfActiveAnimations(frame);
1141 }
1142
1143 void QWEBKIT_EXPORT qt_drt_overwritePluginDirectories()
1144 {
1145     DumpRenderTreeSupportQt::overwritePluginDirectories();
1146 }
1147
1148 bool QWEBKIT_EXPORT qt_drt_pauseAnimation(QWebFrame* frame, const QString& animationName, double time, const QString& elementId)
1149 {
1150     return DumpRenderTreeSupportQt::pauseAnimation(frame, animationName, time, elementId);
1151 }
1152
1153 bool QWEBKIT_EXPORT qt_drt_pauseTransitionOfProperty(QWebFrame* frame, const QString& propertyName, double time, const QString &elementId)
1154 {
1155     return DumpRenderTreeSupportQt::pauseTransitionOfProperty(frame, propertyName, time, elementId);
1156 }
1157
1158 void QWEBKIT_EXPORT qt_drt_resetOriginAccessWhiteLists()
1159 {
1160     DumpRenderTreeSupportQt::resetOriginAccessWhiteLists();
1161 }
1162
1163 void QWEBKIT_EXPORT qt_drt_run(bool b)
1164 {
1165     DumpRenderTreeSupportQt::setDumpRenderTreeModeEnabled(b);
1166 }
1167
1168 void QWEBKIT_EXPORT qt_drt_whiteListAccessFromOrigin(const QString& sourceOrigin, const QString& destinationProtocol, const QString& destinationHost, bool allowDestinationSubdomains)
1169 {
1170     DumpRenderTreeSupportQt::whiteListAccessFromOrigin(sourceOrigin, destinationProtocol, destinationHost, allowDestinationSubdomains);
1171 }
1172
1173 QString QWEBKIT_EXPORT qt_webpage_groupName(QWebPage* page)
1174 {
1175     return DumpRenderTreeSupportQt::webPageGroupName(page);
1176 }
1177
1178 void QWEBKIT_EXPORT qt_webpage_setGroupName(QWebPage* page, const QString& groupName)
1179 {
1180     DumpRenderTreeSupportQt::webPageSetGroupName(page, groupName);
1181 }
1182
1183 void QWEBKIT_EXPORT qt_dump_frame_loader(bool b)
1184 {
1185     DumpRenderTreeSupportQt::dumpFrameLoader(b);
1186 }
1187
1188 void QWEBKIT_EXPORT qt_dump_resource_load_callbacks(bool b)
1189 {
1190     DumpRenderTreeSupportQt::dumpResourceLoadCallbacks(b);
1191 }
1192
1193 void QWEBKIT_EXPORT qt_dump_editing_callbacks(bool b)
1194 {
1195     DumpRenderTreeSupportQt::dumpEditingCallbacks(b);
1196 }
1197
1198 void QWEBKIT_EXPORT qt_dump_set_accepts_editing(bool b)
1199 {
1200     DumpRenderTreeSupportQt::dumpSetAcceptsEditing(b);
1201 }
1202