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