73cb4d7592b1909f14039ee240e9388ebd220e96
[WebKit-https.git] / WebKit / qt / WebCoreSupport / ChromeClientQt.cpp
1 /*
2  * Copyright (C) 2006 Zack Rusin <zack@kde.org>
3  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
4  *
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 #include "config.h"
29 #include "ChromeClientQt.h"
30
31 #include "FileChooser.h"
32 #include "Frame.h"
33 #include "FrameLoadRequest.h"
34 #include "FrameLoader.h"
35 #include "FrameLoaderClientQt.h"
36 #include "FrameView.h"
37 #include "HitTestResult.h"
38 #include "NotImplemented.h"
39 #include "WindowFeatures.h"
40 #include "DatabaseTracker.h"
41 #include "SecurityOrigin.h"
42 #include "QWebPageClient.h"
43
44 #include "qwebpage.h"
45 #include "qwebpage_p.h"
46 #include "qwebframe_p.h"
47 #include "qwebsecurityorigin.h"
48 #include "qwebsecurityorigin_p.h"
49 #include "qwebview.h"
50
51 #include <qtooltip.h>
52 #include <qtextdocument.h>
53
54 namespace WebCore
55 {
56
57
58 ChromeClientQt::ChromeClientQt(QWebPage* webPage)
59     : m_webPage(webPage)
60 {
61     toolBarsVisible = statusBarVisible = menuBarVisible = true;
62 }
63
64 ChromeClientQt::~ChromeClientQt()
65 {
66
67 }
68
69 void ChromeClientQt::setWindowRect(const FloatRect& rect)
70 {
71     if (!m_webPage)
72         return;
73     emit m_webPage->geometryChangeRequested(QRect(qRound(rect.x()), qRound(rect.y()),
74                             qRound(rect.width()), qRound(rect.height())));
75 }
76
77
78 FloatRect ChromeClientQt::windowRect()
79 {
80     if (!m_webPage)
81         return FloatRect();
82
83     QWidget* view = m_webPage->view();
84     if (!view)
85         return FloatRect();
86     return IntRect(view->topLevelWidget()->geometry());
87 }
88
89
90 FloatRect ChromeClientQt::pageRect()
91 {
92     if (!m_webPage)
93         return FloatRect();
94     return FloatRect(QRectF(QPointF(0,0), m_webPage->viewportSize()));
95 }
96
97
98 float ChromeClientQt::scaleFactor()
99 {
100     notImplemented();
101     return 1;
102 }
103
104
105 void ChromeClientQt::focus()
106 {
107     if (!m_webPage)
108         return;
109     QWidget* view = m_webPage->view();
110     if (!view)
111         return;
112
113     view->setFocus();
114 }
115
116
117 void ChromeClientQt::unfocus()
118 {
119     if (!m_webPage)
120         return;
121     QWidget* view = m_webPage->view();
122     if (!view)
123         return;
124     view->clearFocus();
125 }
126
127 bool ChromeClientQt::canTakeFocus(FocusDirection)
128 {
129     // This is called when cycling through links/focusable objects and we
130     // reach the last focusable object. Then we want to claim that we can
131     // take the focus to avoid wrapping.
132     return true;
133 }
134
135 void ChromeClientQt::takeFocus(FocusDirection)
136 {
137     // don't do anything. This is only called when cycling to links/focusable objects,
138     // which in turn is called from focusNextPrevChild. We let focusNextPrevChild
139     // call QWidget::focusNextPrevChild accordingly, so there is no need to do anything
140     // here.
141 }
142
143
144 void ChromeClientQt::focusedNodeChanged(WebCore::Node*)
145 {
146 }
147
148
149 Page* ChromeClientQt::createWindow(Frame*, const FrameLoadRequest& request, const WindowFeatures& features)
150 {
151     QWebPage *newPage = m_webPage->createWindow(features.dialog ? QWebPage::WebModalDialog : QWebPage::WebBrowserWindow);
152     if (!newPage)
153         return 0;
154     newPage->mainFrame()->load(request.resourceRequest().url());
155     return newPage->d->page;
156 }
157
158 void ChromeClientQt::show()
159 {
160     if (!m_webPage)
161         return;
162     QWidget* view = m_webPage->view();
163     if (!view)
164         return;
165     view->topLevelWidget()->show();
166 }
167
168
169 bool ChromeClientQt::canRunModal()
170 {
171     notImplemented();
172     return false;
173 }
174
175
176 void ChromeClientQt::runModal()
177 {
178     notImplemented();
179 }
180
181
182 void ChromeClientQt::setToolbarsVisible(bool visible)
183 {
184     toolBarsVisible = visible;
185     emit m_webPage->toolBarVisibilityChangeRequested(visible);
186 }
187
188
189 bool ChromeClientQt::toolbarsVisible()
190 {
191     return toolBarsVisible;
192 }
193
194
195 void ChromeClientQt::setStatusbarVisible(bool visible)
196 {
197     emit m_webPage->statusBarVisibilityChangeRequested(visible);
198     statusBarVisible = visible;
199 }
200
201
202 bool ChromeClientQt::statusbarVisible()
203 {
204     return statusBarVisible;
205     return false;
206 }
207
208
209 void ChromeClientQt::setScrollbarsVisible(bool)
210 {
211     notImplemented();
212 }
213
214
215 bool ChromeClientQt::scrollbarsVisible()
216 {
217     notImplemented();
218     return true;
219 }
220
221
222 void ChromeClientQt::setMenubarVisible(bool visible)
223 {
224     menuBarVisible = visible;
225     emit m_webPage->menuBarVisibilityChangeRequested(visible);
226 }
227
228 bool ChromeClientQt::menubarVisible()
229 {
230     return menuBarVisible;
231 }
232
233 void ChromeClientQt::setResizable(bool)
234 {
235     notImplemented();
236 }
237
238 void ChromeClientQt::addMessageToConsole(MessageSource, MessageType, MessageLevel, const String& message,
239                                          unsigned int lineNumber, const String& sourceID)
240 {
241     QString x = message;
242     QString y = sourceID;
243     m_webPage->javaScriptConsoleMessage(x, lineNumber, y);
244 }
245
246 void ChromeClientQt::chromeDestroyed()
247 {
248     delete this;
249 }
250
251 bool ChromeClientQt::canRunBeforeUnloadConfirmPanel()
252 {
253     return true;
254 }
255
256 bool ChromeClientQt::runBeforeUnloadConfirmPanel(const String& message, Frame* frame)
257 {
258     return runJavaScriptConfirm(frame, message);
259 }
260
261 void ChromeClientQt::closeWindowSoon()
262 {
263     m_webPage->mainFrame()->d->frame->loader()->stopAllLoaders();
264     emit m_webPage->windowCloseRequested();
265 }
266
267 void ChromeClientQt::runJavaScriptAlert(Frame* f, const String& msg)
268 {
269     QString x = msg;
270     FrameLoaderClientQt *fl = static_cast<FrameLoaderClientQt*>(f->loader()->client());
271     m_webPage->javaScriptAlert(fl->webFrame(), x);
272 }
273
274 bool ChromeClientQt::runJavaScriptConfirm(Frame* f, const String& msg)
275 {
276     QString x = msg;
277     FrameLoaderClientQt *fl = static_cast<FrameLoaderClientQt*>(f->loader()->client());
278     return m_webPage->javaScriptConfirm(fl->webFrame(), x);
279 }
280
281 bool ChromeClientQt::runJavaScriptPrompt(Frame* f, const String& message, const String& defaultValue, String& result)
282 {
283     QString x = result;
284     FrameLoaderClientQt *fl = static_cast<FrameLoaderClientQt*>(f->loader()->client());
285     bool rc = m_webPage->javaScriptPrompt(fl->webFrame(), (QString)message, (QString)defaultValue, &x);
286
287     // Fix up a quirk in the QInputDialog class. If no input happened the string should be empty
288     // but it is null. See https://bugs.webkit.org/show_bug.cgi?id=30914.
289     if (rc && result.isNull())
290         result = String("");
291     else
292         result = x;
293
294     return rc;
295 }
296
297 void ChromeClientQt::setStatusbarText(const String& msg)
298 {
299     QString x = msg;
300     emit m_webPage->statusBarMessage(x);
301 }
302
303 bool ChromeClientQt::shouldInterruptJavaScript()
304 {
305     bool shouldInterrupt = false;
306     QMetaObject::invokeMethod(m_webPage, "shouldInterruptJavaScript", Qt::DirectConnection, Q_RETURN_ARG(bool, shouldInterrupt));
307     return shouldInterrupt;
308 }
309
310 bool ChromeClientQt::tabsToLinks() const
311 {
312     return m_webPage->settings()->testAttribute(QWebSettings::LinksIncludedInFocusChain);
313 }
314
315 IntRect ChromeClientQt::windowResizerRect() const
316 {
317     return IntRect();
318 }
319
320 void ChromeClientQt::repaint(const IntRect& windowRect, bool contentChanged, bool, bool)
321 {
322     // No double buffer, so only update the QWidget if content changed.
323     if (contentChanged) {
324         if (platformPageClient()) {
325             QRect rect(windowRect);
326             rect = rect.intersected(QRect(QPoint(0, 0), m_webPage->viewportSize()));
327             if (!rect.isEmpty())
328                 platformPageClient()->update(rect);
329         }
330         emit m_webPage->repaintRequested(windowRect);
331     }
332
333     // FIXME: There is no "immediate" support for window painting.  This should be done always whenever the flag
334     // is set.
335 }
336
337 void ChromeClientQt::scroll(const IntSize& delta, const IntRect& scrollViewRect, const IntRect&)
338 {
339     if (platformPageClient())
340         platformPageClient()->scroll(delta.width(), delta.height(), scrollViewRect);
341     emit m_webPage->scrollRequested(delta.width(), delta.height(), scrollViewRect);
342 }
343
344 IntRect ChromeClientQt::windowToScreen(const IntRect& rect) const
345 {
346     notImplemented();
347     return rect;
348 }
349
350 IntPoint ChromeClientQt::screenToWindow(const IntPoint& point) const
351 {
352     notImplemented();
353     return point;
354 }
355
356 PlatformPageClient ChromeClientQt::platformPageClient() const
357 {
358     return m_webPage->d->client;
359 }
360
361 void ChromeClientQt::contentsSizeChanged(Frame* frame, const IntSize& size) const
362 {
363     emit QWebFramePrivate::kit(frame)->contentsSizeChanged(size);
364 }
365
366 void ChromeClientQt::mouseDidMoveOverElement(const HitTestResult& result, unsigned)
367 {
368     TextDirection dir;
369     if (result.absoluteLinkURL() != lastHoverURL
370         || result.title(dir) != lastHoverTitle
371         || result.textContent() != lastHoverContent) {
372         lastHoverURL = result.absoluteLinkURL();
373         lastHoverTitle = result.title(dir);
374         lastHoverContent = result.textContent();
375         emit m_webPage->linkHovered(lastHoverURL.prettyURL(),
376                 lastHoverTitle, lastHoverContent);
377     }
378 }
379
380 void ChromeClientQt::setToolTip(const String &tip, TextDirection)
381 {
382 #ifndef QT_NO_TOOLTIP
383     QWidget* view = m_webPage->view();
384     if (!view)
385         return;
386
387     if (tip.isEmpty()) {
388         view->setToolTip(QString());
389         QToolTip::hideText();
390     } else {
391         QString dtip = QLatin1String("<p>") + Qt::escape(tip) + QLatin1String("</p>");
392         view->setToolTip(dtip);
393     }
394 #else
395     Q_UNUSED(tip);
396 #endif
397 }
398
399 void ChromeClientQt::print(Frame *frame)
400 {
401     emit m_webPage->printRequested(QWebFramePrivate::kit(frame));
402 }
403
404 #if ENABLE(DATABASE)
405 void ChromeClientQt::exceededDatabaseQuota(Frame* frame, const String& databaseName)
406 {
407     quint64 quota = QWebSettings::offlineStorageDefaultQuota();
408
409     if (!DatabaseTracker::tracker().hasEntryForOrigin(frame->document()->securityOrigin()))
410         DatabaseTracker::tracker().setQuota(frame->document()->securityOrigin(), quota);
411
412     emit m_webPage->databaseQuotaExceeded(QWebFramePrivate::kit(frame), databaseName);
413 }
414 #endif
415
416 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
417 void ChromeClientQt::reachedMaxAppCacheSize(int64_t)
418 {
419     // FIXME: Free some space.
420     notImplemented();
421 }
422 #endif
423
424 void ChromeClientQt::runOpenPanel(Frame* frame, PassRefPtr<FileChooser> prpFileChooser)
425 {
426     RefPtr<FileChooser> fileChooser = prpFileChooser;
427     bool supportMulti = m_webPage->supportsExtension(QWebPage::ChooseMultipleFilesExtension);
428
429     if (fileChooser->allowsMultipleFiles() && supportMulti) {
430         QWebPage::ChooseMultipleFilesExtensionOption option;
431         option.parentFrame = QWebFramePrivate::kit(frame);
432
433         if (!fileChooser->filenames().isEmpty())
434             for (unsigned i = 0; i < fileChooser->filenames().size(); ++i)
435                 option.suggestedFileNames += fileChooser->filenames()[i];
436
437         QWebPage::ChooseMultipleFilesExtensionReturn output;
438         m_webPage->extension(QWebPage::ChooseMultipleFilesExtension, &option, &output);
439
440         if (!output.fileNames.isEmpty()) {
441             Vector<String> names;
442             for (int i = 0; i < output.fileNames.count(); ++i)
443                 names.append(output.fileNames.at(i));
444             fileChooser->chooseFiles(names);
445         }
446     } else {
447         QString suggestedFile;
448         if (!fileChooser->filenames().isEmpty())
449             suggestedFile = fileChooser->filenames()[0];
450         QString file = m_webPage->chooseFile(QWebFramePrivate::kit(frame), suggestedFile);
451         if (!file.isEmpty())
452             fileChooser->chooseFile(file);
453     }
454 }
455
456 bool ChromeClientQt::setCursor(PlatformCursorHandle)
457 {
458     notImplemented();
459     return false;
460 }
461
462 void ChromeClientQt::requestGeolocationPermissionForFrame(Frame*, Geolocation*)
463 {
464     // See the comment in WebCore/page/ChromeClient.h
465     notImplemented();
466 }
467
468 }