don't put nbsp's into the plan text paste
[WebKit-https.git] / WebKitTools / DumpRenderTree / qt / jsobjects.cpp
1 /*
2  * Copyright (C) 2006 Trolltech ASA
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 #include <jsobjects.h>
29 #include <qwebpage.h>
30 #include <qwebframe.h>
31 #include <qevent.h>
32 #include <qapplication.h>
33 #include <qevent.h>
34
35 #include "DumpRenderTree.h"
36 extern void qt_dump_editing_callbacks(bool b);
37
38 class HackWebFrame : public QWebFrame
39 {
40 public:
41     void mousePressEvent(QMouseEvent *e) {
42         QWebFrame::mousePressEvent(e);
43     }
44     void mouseReleaseEvent(QMouseEvent *e) {
45         QWebFrame::mouseReleaseEvent(e);
46     }
47     void mouseMoveEvent(QMouseEvent *e) {
48         QWebFrame::mouseMoveEvent(e);
49     }
50
51 protected:
52     HackWebFrame(QWebPage *parent, QWebFrameData *frameData) : QWebFrame(parent, frameData) {}
53     HackWebFrame(QWebFrame *parent, QWebFrameData *frameData) : QWebFrame(parent, frameData) {}
54     ~HackWebFrame() {}
55 };
56
57 LayoutTestController::LayoutTestController(WebCore::DumpRenderTree *drt)
58     : QObject()
59     , m_drt(drt)
60 {
61     m_timeoutTimer = 0;
62     reset();
63 }
64
65 void LayoutTestController::reset()
66 {
67     m_isLoading = true;
68     m_textDump = false;
69     m_dumpChildrenAsText = false;
70     m_canOpenWindows = false;
71     m_waitForDone = false;
72     m_dumpTitleChanges = false;
73     if (m_timeoutTimer) {
74         killTimer(m_timeoutTimer);
75         m_timeoutTimer = 0;
76     }
77     m_topLoadingFrame = 0;
78     qt_dump_editing_callbacks(false);
79 }
80
81 void LayoutTestController::maybeDump(bool ok)
82 {
83     QWebFrame *frame = qobject_cast<QWebFrame*>(sender());
84     if (frame != m_topLoadingFrame)
85         return;
86
87     m_topLoadingFrame = 0;
88
89     if (!shouldWaitUntilDone()) {
90         emit done();
91         m_isLoading = false;
92     }
93 }
94
95 void LayoutTestController::waitUntilDone()
96 {
97     //qDebug() << ">>>>waitForDone";
98     m_waitForDone = true;
99     m_timeoutTimer = startTimer(5000);
100 }
101
102 void LayoutTestController::notifyDone()
103 {
104     //qDebug() << ">>>>notifyDone";
105     if (!m_timeoutTimer)
106         return;
107     killTimer(m_timeoutTimer);
108     m_timeoutTimer = 0;
109     emit done();
110     m_isLoading = false;
111 }
112
113 int LayoutTestController::windowCount()
114 {
115     return m_drt->windowCount();
116 }
117
118 void LayoutTestController::clearBackForwardList()
119 {
120     m_drt->webPage()->history().clear();
121 }
122
123
124 void LayoutTestController::dumpEditingCallbacks()
125 {
126     qDebug() << ">>>dumpEditingCallbacks";
127     qt_dump_editing_callbacks(true);
128 }
129
130 void LayoutTestController::queueReload()
131 {
132     //qDebug() << ">>>queueReload";
133 }
134
135 void LayoutTestController::provisionalLoad()
136 {
137     QWebFrame *frame = qobject_cast<QWebFrame*>(sender());
138     if (!m_topLoadingFrame && m_isLoading)
139         m_topLoadingFrame = frame;
140 }
141
142 void LayoutTestController::timerEvent(QTimerEvent *)
143 {
144     qDebug() << ">>>>>>>>>>>>> timeout";
145     notifyDone();
146 }
147
148 QString LayoutTestController::encodeHostName(const QString &host)
149 {
150     QString encoded = QString::fromLatin1(QUrl::toAce(host + QLatin1String(".no")));
151     encoded.truncate(encoded.length() - 3); // strip .no
152     return encoded;
153 }
154
155 QString LayoutTestController::decodeHostName(const QString &host)
156 {
157     QString decoded = QUrl::fromAce(host.toLatin1() + QByteArray(".no"));
158     decoded.truncate(decoded.length() - 3);
159     return decoded;
160 }
161
162
163 EventSender::EventSender(QWebPage *parent)
164     : QObject(parent)
165 {
166     m_page = parent;
167 }
168
169 void EventSender::mouseDown()
170 {
171     QWebFrame *frame = frameUnderMouse();
172 //     qDebug() << "EventSender::mouseDown" << frame;
173     if (!frame)
174         return;
175     QMouseEvent event(QEvent::MouseButtonPress, m_mousePos - frame->pos(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
176     static_cast<HackWebFrame *>(frame)->mousePressEvent(&event);
177 }
178
179 void EventSender::mouseUp()
180 {
181     QWebFrame *frame = frameUnderMouse();
182 //     qDebug() << "EventSender::mouseUp" << frame;
183     if (!frame)
184         return;
185     QMouseEvent event(QEvent::MouseButtonRelease, m_mousePos - frame->pos(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
186     static_cast<HackWebFrame *>(frame)->mouseReleaseEvent(&event);
187 }
188
189 void EventSender::mouseMoveTo(int x, int y)
190 {
191     QWebFrame *frame = frameUnderMouse();
192 //     qDebug() << "EventSender::mouseMoveTo" << x << y;
193     m_mousePos = QPoint(x, y);
194     QMouseEvent event(QEvent::MouseMove, m_mousePos - frame->pos(), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
195     static_cast<HackWebFrame *>(frame)->mouseMoveEvent(&event);
196 }
197
198 void EventSender::leapForward(int ms)
199 {
200     m_timeLeap += ms;
201     qDebug() << "EventSender::leapForward" << ms;
202 }
203
204 void EventSender::keyDown(const QString &string, const QStringList &modifiers)
205 {
206     QString s = string;
207     Qt::KeyboardModifiers modifs = 0;
208     for (int i = 0; i < modifiers.size(); ++i) {
209         const QString &m = modifiers.at(i);
210         if (m == "ctrlKey")
211             modifs |= Qt::ControlModifier;
212         else if (m == "shiftKey")
213             modifs |= Qt::ShiftModifier;
214         else if (m == "altKey")
215             modifs |= Qt::AltModifier;
216         else if (m == "metaKey")
217             modifs |= Qt::MetaModifier;
218     }
219     int code = 0;
220     if (string.length() == 1) {
221         code = string.unicode()->unicode();
222         qDebug() << ">>>>>>>>> keyDown" << code << (char)code;
223         // map special keycodes used by the tests to something that works for Qt/X11
224         if (code == '\t') {
225             code = Qt::Key_Tab;
226             if (modifs == Qt::ShiftModifier)
227                 code = Qt::Key_Backtab;
228             s = QString();
229         } else if (code == 127) {
230             code = Qt::Key_Backspace;
231             if (modifs == Qt::AltModifier)
232                 modifs = Qt::ControlModifier;
233             s = QString();
234         } else if (code == 'o' && modifs == Qt::ControlModifier) {
235             s = QLatin1String("\n");
236             code = '\n';
237             modifs = 0;
238         } else if (code == 'y' && modifs == Qt::ControlModifier) {
239             s = QLatin1String("c");
240             code = 'c';
241         } else if (code == 'k' && modifs == Qt::ControlModifier) {
242             s = QLatin1String("x");
243             code = 'x';
244         } else if (code == 'a' && modifs == Qt::ControlModifier) {
245             s = QString();
246             code = Qt::Key_Home;
247             modifs = 0;
248         } else if (code == 0xf702) {
249             s = QString();
250             code = Qt::Key_Left;
251             if (modifs & Qt::MetaModifier) {
252                 code = Qt::Key_Home;
253                 modifs &= ~Qt::MetaModifier;
254             }
255         } else if (code == 0xf703) {
256             s = QString();
257             code = Qt::Key_Right;
258             if (modifs & Qt::MetaModifier) {
259                 code = Qt::Key_End;
260                 modifs &= ~Qt::MetaModifier;
261             }
262         } else if (code == 'a' && modifs == Qt::ControlModifier) {
263             s = QString();
264             code = Qt::Key_Home;
265             modifs = 0;
266         } else {
267             code = string.unicode()->toUpper().unicode();
268         }
269     }
270     QKeyEvent event(QEvent::KeyPress, code, modifs, s);
271     QApplication::sendEvent(m_page, &event);
272 }
273
274 QWebFrame *EventSender::frameUnderMouse() const
275 {
276     QWebFrame *frame = m_page->mainFrame();
277
278 redo:
279     QList<QWebFrame*> children = frame->childFrames();
280     for (int i = 0; i < children.size(); ++i) {
281         if (children.at(i)->geometry().contains(m_mousePos)) {
282             frame = children.at(i);
283             goto redo;
284         }
285     }
286     if (frame->geometry().contains(m_mousePos))
287         return frame;
288     return 0;
289 }
290
291
292 TextInputController::TextInputController(QWebPage *parent)
293     : QObject(parent)
294 {
295 }
296
297 void TextInputController::doCommand(const QString &command)
298 {
299     Qt::KeyboardModifiers modifiers = Qt::NoModifier;
300     int keycode = 0;
301     if (command == "moveBackwardAndModifySelection:") {
302         modifiers |= Qt::ShiftModifier;
303         keycode = Qt::Key_Left;
304     } else if(command =="moveDown:") {
305         keycode = Qt::Key_Down;
306     } else if(command =="moveDownAndModifySelection:") {
307         modifiers |= Qt::ShiftModifier;
308         keycode = Qt::Key_Down;
309     } else if(command =="moveForward:") {
310         keycode = Qt::Key_Right;
311     } else if(command =="moveForwardAndModifySelection:") {
312         modifiers |= Qt::ShiftModifier;
313         keycode = Qt::Key_Right;
314     } else if(command =="moveLeft:") {
315         keycode = Qt::Key_Left;
316     } else if(command =="moveLeftAndModifySelection:") {
317         modifiers |= Qt::ShiftModifier;
318         keycode = Qt::Key_Left;
319     } else if(command =="moveRight:") {
320         keycode = Qt::Key_Right;
321     } else if(command =="moveRightAndModifySelection:") {
322         modifiers |= Qt::ShiftModifier;
323         keycode = Qt::Key_Right;
324     } else if(command =="moveToBeginningOfDocument:") {
325         modifiers |= Qt::ControlModifier;
326         keycode = Qt::Key_Home;
327     } else if(command =="moveToBeginningOfLine:") {
328         keycode = Qt::Key_Home;
329 //     } else if(command =="moveToBeginningOfParagraph:") {
330     } else if(command =="moveToEndOfDocument:") {
331         modifiers |= Qt::ControlModifier;
332         keycode = Qt::Key_End;
333     } else if(command =="moveToEndOfLine:") {
334         keycode = Qt::Key_End;
335 //     } else if(command =="moveToEndOfParagraph:") {
336     } else if(command =="moveUp:") {
337         keycode = Qt::Key_Up;
338     } else if(command =="moveUpAndModifySelection:") {
339         modifiers |= Qt::ShiftModifier;
340         keycode = Qt::Key_Up;
341     } else if(command =="moveWordBackward:") {
342         modifiers |= Qt::ControlModifier;
343         keycode = Qt::Key_Up;
344     } else if(command =="moveWordBackwardAndModifySelection:") {
345         modifiers |= Qt::ShiftModifier;
346         modifiers |= Qt::ControlModifier;
347         keycode = Qt::Key_Left;
348     } else if(command =="moveWordForward:") {
349         modifiers |= Qt::ControlModifier;
350         keycode = Qt::Key_Right;
351     } else if(command =="moveWordForwardAndModifySelection:") {
352         modifiers |= Qt::ControlModifier;
353         modifiers |= Qt::ShiftModifier;
354         keycode = Qt::Key_Right;
355     } else if(command =="moveWordLeft:") {
356         modifiers |= Qt::ControlModifier;
357         keycode = Qt::Key_Left;
358     } else if(command =="moveWordRight:") {
359         modifiers |= Qt::ControlModifier;
360         keycode = Qt::Key_Left;
361     } else if(command =="moveWordRightAndModifySelection:") {
362         modifiers |= Qt::ShiftModifier;
363         modifiers |= Qt::ControlModifier;
364         keycode = Qt::Key_Right;
365     } else if(command =="moveWordLeftAndModifySelection:") {
366         modifiers |= Qt::ShiftModifier;
367         modifiers |= Qt::ControlModifier;
368         keycode = Qt::Key_Left;
369     } else if(command =="pageDown:") {
370         keycode = Qt::Key_PageDown;        
371     } else if(command =="pageUp:") {
372         keycode = Qt::Key_PageUp;        
373     } else if(command == "deleteWordBackward:") {
374         modifiers |= Qt::ControlModifier;
375         keycode = Qt::Key_Backspace;
376     } else if(command == "deleteBackward:") {
377         keycode = Qt::Key_Backspace;
378     } else if(command == "deleteForward:") {
379         keycode = Qt::Key_Delete;
380     }
381     QKeyEvent event(QEvent::KeyPress, keycode, modifiers);
382     QApplication::sendEvent(parent(), &event);
383     QKeyEvent event2(QEvent::KeyRelease, keycode, modifiers);
384     QApplication::sendEvent(parent(), &event2);
385 }