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