1 /*
2     Copyright (C) 2008, 2009 Nokia Corporation and/or its subsidiary(-ies)
3     Copyright (C) 2007 Staikos Computing Services Inc.
4     Copyright (C) 2007 Apple Inc.
5 
6     This library is free software; you can redistribute it and/or
7     modify it under the terms of the GNU Library General Public
8     License as published by the Free Software Foundation; either
9     version 2 of the License, or (at your option) any later version.
10 
11     This library is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14     Library General Public License for more details.
15 
16     You should have received a copy of the GNU Library General Public License
17     along with this library; see the file COPYING.LIB.  If not, write to
18     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19     Boston, MA 02110-1301, USA.
20 */
21 
22 #include "config.h"
23 #include "qwebpage.h"
24 
25 #include "qwebview.h"
26 #include "qwebframe.h"
27 #include "qwebpage_p.h"
28 #include "qwebframe_p.h"
29 #include "qwebhistory.h"
30 #include "qwebhistory_p.h"
31 #include "qwebinspector.h"
32 #include "qwebinspector_p.h"
33 #include "qwebsettings.h"
34 #include "qwebkitplatformplugin.h"
35 #include "qwebkitversion.h"
36 
37 #include "CSSComputedStyleDeclaration.h"
38 #include "CSSParser.h"
39 #include "ApplicationCacheStorage.h"
40 #include "BackForwardListImpl.h"
41 #include "MemoryCache.h"
42 #include "Chrome.h"
43 #include "ChromeClientQt.h"
44 #include "ClientRect.h"
45 #include "ContextMenu.h"
46 #include "ContextMenuClientQt.h"
47 #include "ContextMenuController.h"
48 #include "DeviceMotionClientQt.h"
49 #include "DeviceOrientationClientQt.h"
50 #include "DocumentLoader.h"
51 #include "DragClientQt.h"
52 #include "DragController.h"
53 #include "DragData.h"
54 #include "Editor.h"
55 #include "EditorClientQt.h"
56 #include "FocusController.h"
57 #include "FormState.h"
58 #include "Frame.h"
59 #include "FrameLoadRequest.h"
60 #include "FrameLoader.h"
61 #include "FrameLoader.h"
62 #include "FrameLoaderClientQt.h"
63 #include "FrameTree.h"
64 #include "FrameView.h"
65 #if ENABLE(CLIENT_BASED_GEOLOCATION)
66 #include "GeolocationClientMock.h"
67 #include "GeolocationClientQt.h"
68 #endif // CLIENT_BASED_GEOLOCATION
69 #include "GeolocationPermissionClientQt.h"
70 #include "HTMLFormElement.h"
71 #include "HTMLFrameOwnerElement.h"
72 #include "HTMLInputElement.h"
73 #include "HTMLNames.h"
74 #include "HashMap.h"
75 #include "HitTestResult.h"
76 #include "Image.h"
77 #include "InspectorClientQt.h"
78 #include "InspectorController.h"
79 #include "InspectorServerQt.h"
80 #include "KURL.h"
81 #include "LocalizedStrings.h"
82 #include "Logging.h"
83 #include "MIMETypeRegistry.h"
84 #include "NavigationAction.h"
85 #include "NetworkingContext.h"
86 #include "NodeList.h"
87 #include "NotificationPresenterClientQt.h"
88 #include "NotImplemented.h"
89 #include "Page.h"
90 #include "PageClientQt.h"
91 #include "PageGroup.h"
92 #include "Pasteboard.h"
93 #include "PlatformKeyboardEvent.h"
94 #include "PlatformTouchEvent.h"
95 #include "PlatformWheelEvent.h"
96 #include "PluginDatabase.h"
97 #include "PluginDatabase.h"
98 #include "PluginPackage.h"
99 #include "ProgressTracker.h"
100 #include "QtPlatformPlugin.h"
101 #include "RefPtr.h"
102 #include "RenderTextControl.h"
103 #include "SchemeRegistry.h"
104 #include "Scrollbar.h"
105 #include "SecurityOrigin.h"
106 #include "Settings.h"
107 #if defined Q_OS_WIN32
108 #include "SystemInfo.h"
109 #endif // Q_OS_WIN32
110 #include "TextIterator.h"
111 #include "WebPlatformStrategies.h"
112 #if USE(QTKIT)
113 #include "WebSystemInterface.h"
114 #endif
115 #include "WindowFeatures.h"
116 #include "WorkerThread.h"
117 #include "runtime/InitializeThreading.h"
118 #include "wtf/Threading.h"
119 
120 #include <QApplication>
121 #include <QBasicTimer>
122 #include <QBitArray>
123 #include <QDebug>
124 #include <QDesktopWidget>
125 #include <QDragEnterEvent>
126 #include <QDragLeaveEvent>
127 #include <QDragMoveEvent>
128 #include <QDropEvent>
129 #include <QFileDialog>
130 #include <QHttpRequestHeader>
131 #include <QInputDialog>
132 #include <QMessageBox>
133 #include <QNetworkProxy>
134 #include <QUndoStack>
135 #include <QUrl>
136 #include <QPainter>
137 #include <QClipboard>
138 #include <QSslSocket>
139 #include <QStyle>
140 #include <QSysInfo>
141 #include <QTextCharFormat>
142 #include <QTextDocument>
143 #include <QTouchEvent>
144 #include <QNetworkAccessManager>
145 #include <QNetworkRequest>
146 #if defined(Q_WS_X11)
147 #include <QX11Info>
148 #endif
149 #if USE(QT_MOBILITY_SYSTEMINFO)
150 #include <qsysteminfo.h>
151 #endif
152 
153 using namespace WebCore;
154 
155 // from text/qfont.cpp
156 QT_BEGIN_NAMESPACE
157 extern Q_GUI_EXPORT int qt_defaultDpi();
158 QT_END_NAMESPACE
159 
160 bool QWebPagePrivate::drtRun = false;
161 
162 // Lookup table mapping QWebPage::WebActions to the associated Editor commands
163 static const char* editorCommandWebActions[] =
164 {
165     0, // OpenLink,
166 
167     0, // OpenLinkInNewWindow,
168     0, // OpenFrameInNewWindow,
169 
170     0, // DownloadLinkToDisk,
171     0, // CopyLinkToClipboard,
172 
173     0, // OpenImageInNewWindow,
174     0, // DownloadImageToDisk,
175     0, // CopyImageToClipboard,
176 
177     0, // Back,
178     0, // Forward,
179     0, // Stop,
180     0, // Reload,
181 
182     "Cut", // Cut,
183     "Copy", // Copy,
184     "Paste", // Paste,
185 
186     "Undo", // Undo,
187     "Redo", // Redo,
188     "MoveForward", // MoveToNextChar,
189     "MoveBackward", // MoveToPreviousChar,
190     "MoveWordForward", // MoveToNextWord,
191     "MoveWordBackward", // MoveToPreviousWord,
192     "MoveDown", // MoveToNextLine,
193     "MoveUp", // MoveToPreviousLine,
194     "MoveToBeginningOfLine", // MoveToStartOfLine,
195     "MoveToEndOfLine", // MoveToEndOfLine,
196     "MoveToBeginningOfParagraph", // MoveToStartOfBlock,
197     "MoveToEndOfParagraph", // MoveToEndOfBlock,
198     "MoveToBeginningOfDocument", // MoveToStartOfDocument,
199     "MoveToEndOfDocument", // MoveToEndOfDocument,
200     "MoveForwardAndModifySelection", // SelectNextChar,
201     "MoveBackwardAndModifySelection", // SelectPreviousChar,
202     "MoveWordForwardAndModifySelection", // SelectNextWord,
203     "MoveWordBackwardAndModifySelection", // SelectPreviousWord,
204     "MoveDownAndModifySelection", // SelectNextLine,
205     "MoveUpAndModifySelection", // SelectPreviousLine,
206     "MoveToBeginningOfLineAndModifySelection", // SelectStartOfLine,
207     "MoveToEndOfLineAndModifySelection", // SelectEndOfLine,
208     "MoveToBeginningOfParagraphAndModifySelection", // SelectStartOfBlock,
209     "MoveToEndOfParagraphAndModifySelection", // SelectEndOfBlock,
210     "MoveToBeginningOfDocumentAndModifySelection", //SelectStartOfDocument,
211     "MoveToEndOfDocumentAndModifySelection", // SelectEndOfDocument,
212     "DeleteWordBackward", // DeleteStartOfWord,
213     "DeleteWordForward", // DeleteEndOfWord,
214 
215     0, // SetTextDirectionDefault,
216     0, // SetTextDirectionLeftToRight,
217     0, // SetTextDirectionRightToLeft,
218 
219     "ToggleBold", // ToggleBold,
220     "ToggleItalic", // ToggleItalic,
221     "ToggleUnderline", // ToggleUnderline,
222 
223     0, // InspectElement,
224 
225     "InsertNewline", // InsertParagraphSeparator
226     "InsertLineBreak", // InsertLineSeparator
227 
228     "SelectAll", // SelectAll
229     0, // ReloadAndBypassCache,
230 
231     "PasteAndMatchStyle", // PasteAndMatchStyle
232     "RemoveFormat", // RemoveFormat
233     "Strikethrough", // ToggleStrikethrough,
234     "Subscript", // ToggleSubscript
235     "Superscript", // ToggleSuperscript
236     "InsertUnorderedList", // InsertUnorderedList
237     "InsertOrderedList", // InsertOrderedList
238     "Indent", // Indent
239     "Outdent", // Outdent,
240 
241     "AlignCenter", // AlignCenter,
242     "AlignJustified", // AlignJustified,
243     "AlignLeft", // AlignLeft,
244     "AlignRight", // AlignRight,
245 
246     0, // StopScheduledPageRefresh,
247 
248     0, // CopyImageUrlToClipboard,
249 
250     0 // WebActionCount
251 };
252 
253 // Lookup the appropriate editor command to use for WebAction \a action
editorCommandForWebActions(QWebPage::WebAction action)254 const char* QWebPagePrivate::editorCommandForWebActions(QWebPage::WebAction action)
255 {
256     if ((action > QWebPage::NoWebAction) && (action < int(sizeof(editorCommandWebActions) / sizeof(const char*))))
257         return editorCommandWebActions[action];
258     return 0;
259 }
260 
dropActionToDragOp(Qt::DropActions actions)261 static inline DragOperation dropActionToDragOp(Qt::DropActions actions)
262 {
263     unsigned result = 0;
264     if (actions & Qt::CopyAction)
265         result |= DragOperationCopy;
266     // DragOperationgeneric represents InternetExplorer's equivalent of Move operation,
267     // hence it should be considered as "move"
268     if (actions & Qt::MoveAction)
269         result |= (DragOperationMove | DragOperationGeneric);
270     if (actions & Qt::LinkAction)
271         result |= DragOperationLink;
272     if (result == (DragOperationCopy | DragOperationMove | DragOperationGeneric | DragOperationLink))
273         result = DragOperationEvery;
274     return (DragOperation)result;
275 }
276 
dragOpToDropAction(unsigned actions)277 static inline Qt::DropAction dragOpToDropAction(unsigned actions)
278 {
279     Qt::DropAction result = Qt::IgnoreAction;
280     if (actions & DragOperationCopy)
281         result = Qt::CopyAction;
282     else if (actions & DragOperationMove)
283         result = Qt::MoveAction;
284     // DragOperationgeneric represents InternetExplorer's equivalent of Move operation,
285     // hence it should be considered as "move"
286     else if (actions & DragOperationGeneric)
287         result = Qt::MoveAction;
288     else if (actions & DragOperationLink)
289         result = Qt::LinkAction;
290     return result;
291 }
292 
QWebPagePrivate(QWebPage * qq)293 QWebPagePrivate::QWebPagePrivate(QWebPage *qq)
294     : q(qq)
295     , page(0)
296     , mainFrame(0)
297 #ifndef QT_NO_UNDOSTACK
298     , undoStack(0)
299 #endif
300     , insideOpenCall(false)
301     , m_totalBytes(0)
302     , m_bytesReceived()
303     , clickCausedFocus(false)
304     , networkManager(0)
305     , forwardUnsupportedContent(false)
306     , smartInsertDeleteEnabled(true)
307     , selectTrailingWhitespaceEnabled(false)
308     , linkPolicy(QWebPage::DontDelegateLinks)
309     , viewportSize(QSize(0, 0))
310     , pixelRatio(1)
311 #ifndef QT_NO_CONTEXTMENU
312     , currentContextMenu(0)
313 #endif
314     , settings(0)
315     , useFixedLayout(false)
316     , pluginFactory(0)
317     , inspectorFrontend(0)
318     , inspector(0)
319     , inspectorIsInternalOnly(false)
320     , m_lastDropAction(Qt::IgnoreAction)
321 {
322     WebCore::InitializeLoggingChannelsIfNecessary();
323     ScriptController::initializeThreading();
324     WTF::initializeMainThread();
325     WebCore::SecurityOrigin::setLocalLoadPolicy(WebCore::SecurityOrigin::AllowLocalLoadsForLocalAndSubstituteData);
326 
327     WebPlatformStrategies::initialize();
328 
329 #if USE(QTKIT)
330     InitWebCoreSystemInterface();
331 #endif
332 
333     Page::PageClients pageClients;
334     pageClients.chromeClient = new ChromeClientQt(q);
335     pageClients.contextMenuClient = new ContextMenuClientQt();
336     pageClients.editorClient = new EditorClientQt(q);
337     pageClients.dragClient = new DragClientQt(q);
338     pageClients.inspectorClient = new InspectorClientQt(q);
339 #if ENABLE(DEVICE_ORIENTATION)
340     pageClients.deviceOrientationClient = new DeviceOrientationClientQt(q);
341     pageClients.deviceMotionClient = new DeviceMotionClientQt(q);
342 #endif
343 #if ENABLE(CLIENT_BASED_GEOLOCATION)
344     if (QWebPagePrivate::drtRun)
345         pageClients.geolocationClient = new GeolocationClientMock();
346     else
347         pageClients.geolocationClient = new GeolocationClientQt(q);
348 #endif
349     page = new Page(pageClients);
350 
351     // By default each page is put into their own unique page group, which affects popup windows
352     // and visited links. Page groups (per process only) is a feature making it possible to use
353     // separate settings for each group, so that for instance an integrated browser/email reader
354     // can use different settings for displaying HTML pages and HTML email. To make QtWebKit work
355     // as expected out of the box, we use a default group similar to what other ports are doing.
356     page->setGroupName("Default Group");
357 
358 #if ENABLE(CLIENT_BASED_GEOLOCATION)
359     // In case running in DumpRenderTree mode set the controller to mock provider.
360     if (QWebPagePrivate::drtRun)
361         static_cast<GeolocationClientMock*>(pageClients.geolocationClient)->setController(page->geolocationController());
362 #endif
363     settings = new QWebSettings(page->settings());
364 
365     history.d = new QWebHistoryPrivate(static_cast<WebCore::BackForwardListImpl*>(page->backForwardList()));
366     memset(actions, 0, sizeof(actions));
367 
368     PageGroup::setShouldTrackVisitedLinks(true);
369 
370 #if ENABLE(NOTIFICATIONS)
371     NotificationPresenterClientQt::notificationPresenter()->addClient();
372 #endif
373 }
374 
~QWebPagePrivate()375 QWebPagePrivate::~QWebPagePrivate()
376 {
377     if (inspector && inspectorIsInternalOnly) {
378         // Since we have to delete an internal inspector,
379         // call setInspector(0) directly to prevent potential crashes
380         setInspector(0);
381     }
382 #ifndef QT_NO_CONTEXTMENU
383     delete currentContextMenu;
384 #endif
385 #ifndef QT_NO_UNDOSTACK
386     delete undoStack;
387 #endif
388     delete settings;
389     delete page;
390 
391     if (inspector)
392         inspector->setPage(0);
393 
394 #if ENABLE(NOTIFICATIONS)
395     NotificationPresenterClientQt::notificationPresenter()->removeClient();
396 #endif
397 }
398 
viewportArguments()399 WebCore::ViewportArguments QWebPagePrivate::viewportArguments()
400 {
401     return page ? page->viewportArguments() : WebCore::ViewportArguments();
402 }
403 
core(const QWebPage * page)404 WebCore::Page* QWebPagePrivate::core(const QWebPage* page)
405 {
406     return page->d->page;
407 }
408 
priv(QWebPage * page)409 QWebPagePrivate* QWebPagePrivate::priv(QWebPage* page)
410 {
411     return page->d;
412 }
413 
acceptNavigationRequest(QWebFrame * frame,const QNetworkRequest & request,QWebPage::NavigationType type)414 bool QWebPagePrivate::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
415 {
416     if (insideOpenCall
417         && frame == mainFrame)
418         return true;
419     return q->acceptNavigationRequest(frame, request, type);
420 }
421 
createMainFrame()422 void QWebPagePrivate::createMainFrame()
423 {
424     if (!mainFrame) {
425         QWebFrameData frameData(page);
426         mainFrame = new QWebFrame(q, &frameData);
427 
428         emit q->frameCreated(mainFrame);
429     }
430 }
431 
webActionForContextMenuAction(WebCore::ContextMenuAction action)432 static QWebPage::WebAction webActionForContextMenuAction(WebCore::ContextMenuAction action)
433 {
434     switch (action) {
435         case WebCore::ContextMenuItemTagOpenLink: return QWebPage::OpenLink;
436         case WebCore::ContextMenuItemTagOpenLinkInNewWindow: return QWebPage::OpenLinkInNewWindow;
437         case WebCore::ContextMenuItemTagDownloadLinkToDisk: return QWebPage::DownloadLinkToDisk;
438         case WebCore::ContextMenuItemTagCopyLinkToClipboard: return QWebPage::CopyLinkToClipboard;
439         case WebCore::ContextMenuItemTagOpenImageInNewWindow: return QWebPage::OpenImageInNewWindow;
440         case WebCore::ContextMenuItemTagDownloadImageToDisk: return QWebPage::DownloadImageToDisk;
441         case WebCore::ContextMenuItemTagCopyImageToClipboard: return QWebPage::CopyImageToClipboard;
442         case WebCore::ContextMenuItemTagCopyImageUrlToClipboard: return QWebPage::CopyImageUrlToClipboard;
443         case WebCore::ContextMenuItemTagOpenFrameInNewWindow: return QWebPage::OpenFrameInNewWindow;
444         case WebCore::ContextMenuItemTagCopy: return QWebPage::Copy;
445         case WebCore::ContextMenuItemTagGoBack: return QWebPage::Back;
446         case WebCore::ContextMenuItemTagGoForward: return QWebPage::Forward;
447         case WebCore::ContextMenuItemTagStop: return QWebPage::Stop;
448         case WebCore::ContextMenuItemTagReload: return QWebPage::Reload;
449         case WebCore::ContextMenuItemTagCut: return QWebPage::Cut;
450         case WebCore::ContextMenuItemTagPaste: return QWebPage::Paste;
451         case WebCore::ContextMenuItemTagDefaultDirection: return QWebPage::SetTextDirectionDefault;
452         case WebCore::ContextMenuItemTagLeftToRight: return QWebPage::SetTextDirectionLeftToRight;
453         case WebCore::ContextMenuItemTagRightToLeft: return QWebPage::SetTextDirectionRightToLeft;
454         case WebCore::ContextMenuItemTagBold: return QWebPage::ToggleBold;
455         case WebCore::ContextMenuItemTagItalic: return QWebPage::ToggleItalic;
456         case WebCore::ContextMenuItemTagUnderline: return QWebPage::ToggleUnderline;
457         case WebCore::ContextMenuItemTagSelectAll: return QWebPage::SelectAll;
458 #if ENABLE(INSPECTOR)
459         case WebCore::ContextMenuItemTagInspectElement: return QWebPage::InspectElement;
460 #endif
461         default: break;
462     }
463     return QWebPage::NoWebAction;
464 }
465 
466 #ifndef QT_NO_CONTEXTMENU
createContextMenu(const WebCore::ContextMenu * webcoreMenu,const QList<WebCore::ContextMenuItem> * items,QBitArray * visitedWebActions)467 QMenu *QWebPagePrivate::createContextMenu(const WebCore::ContextMenu *webcoreMenu,
468         const QList<WebCore::ContextMenuItem> *items, QBitArray *visitedWebActions)
469 {
470     if (!client || !webcoreMenu)
471         return 0;
472 
473     QMenu* menu = new QMenu(client->ownerWidget());
474     for (int i = 0; i < items->count(); ++i) {
475         const ContextMenuItem &item = items->at(i);
476         switch (item.type()) {
477             case WebCore::CheckableActionType: /* fall through */
478             case WebCore::ActionType: {
479                 QWebPage::WebAction action = webActionForContextMenuAction(item.action());
480                 QAction *a = q->action(action);
481                 if (a) {
482                     ContextMenuItem it(item);
483                     page->contextMenuController()->checkOrEnableIfNeeded(it);
484                     PlatformMenuItemDescription desc = it.releasePlatformDescription();
485                     a->setEnabled(desc.enabled);
486                     a->setChecked(desc.checked);
487                     a->setCheckable(item.type() == WebCore::CheckableActionType);
488 
489                     menu->addAction(a);
490                     visitedWebActions->setBit(action);
491                 }
492                 break;
493             }
494             case WebCore::SeparatorType:
495                 menu->addSeparator();
496                 break;
497             case WebCore::SubmenuType: {
498                 QMenu *subMenu = createContextMenu(webcoreMenu, item.platformSubMenu(), visitedWebActions);
499 
500                 bool anyEnabledAction = false;
501 
502                 QList<QAction *> actions = subMenu->actions();
503                 for (int i = 0; i < actions.count(); ++i) {
504                     if (actions.at(i)->isVisible())
505                         anyEnabledAction |= actions.at(i)->isEnabled();
506                 }
507 
508                 // don't show sub-menus with just disabled actions
509                 if (anyEnabledAction) {
510                     subMenu->setTitle(item.title());
511                     menu->addAction(subMenu->menuAction());
512                 } else
513                     delete subMenu;
514                 break;
515             }
516         }
517     }
518     return menu;
519 }
520 #endif // QT_NO_CONTEXTMENU
521 
522 #ifndef QT_NO_ACTION
_q_webActionTriggered(bool checked)523 void QWebPagePrivate::_q_webActionTriggered(bool checked)
524 {
525     QAction *a = qobject_cast<QAction *>(q->sender());
526     if (!a)
527         return;
528     QWebPage::WebAction action = static_cast<QWebPage::WebAction>(a->data().toInt());
529     q->triggerAction(action, checked);
530 }
531 #endif // QT_NO_ACTION
532 
_q_cleanupLeakMessages()533 void QWebPagePrivate::_q_cleanupLeakMessages()
534 {
535 #ifndef NDEBUG
536     // Need this to make leak messages accurate.
537     memoryCache()->setCapacities(0, 0, 0);
538 #endif
539 }
540 
updateAction(QWebPage::WebAction action)541 void QWebPagePrivate::updateAction(QWebPage::WebAction action)
542 {
543 #ifdef QT_NO_ACTION
544     Q_UNUSED(action)
545 #else
546     QAction *a = actions[action];
547     if (!a || !mainFrame)
548         return;
549 
550     WebCore::FrameLoader *loader = mainFrame->d->frame->loader();
551     WebCore::Editor *editor = page->focusController()->focusedOrMainFrame()->editor();
552 
553     bool enabled = a->isEnabled();
554     bool checked = a->isChecked();
555 
556     switch (action) {
557         case QWebPage::Back:
558             enabled = page->canGoBackOrForward(-1);
559             break;
560         case QWebPage::Forward:
561             enabled = page->canGoBackOrForward(1);
562             break;
563         case QWebPage::Stop:
564             enabled = loader->isLoading();
565             break;
566         case QWebPage::Reload:
567         case QWebPage::ReloadAndBypassCache:
568             enabled = !loader->isLoading();
569             break;
570 #ifndef QT_NO_UNDOSTACK
571         case QWebPage::Undo:
572         case QWebPage::Redo:
573             // those two are handled by QUndoStack
574             break;
575 #endif // QT_NO_UNDOSTACK
576         case QWebPage::SelectAll: // editor command is always enabled
577             break;
578         case QWebPage::SetTextDirectionDefault:
579         case QWebPage::SetTextDirectionLeftToRight:
580         case QWebPage::SetTextDirectionRightToLeft:
581             enabled = editor->canEdit();
582             checked = false;
583             break;
584         default: {
585             // see if it's an editor command
586             const char* commandName = editorCommandForWebActions(action);
587 
588             // if it's an editor command, let it's logic determine state
589             if (commandName) {
590                 Editor::Command command = editor->command(commandName);
591                 enabled = command.isEnabled();
592                 if (enabled)
593                     checked = command.state() != FalseTriState;
594                 else
595                     checked = false;
596             }
597             break;
598         }
599     }
600 
601     a->setEnabled(enabled);
602 
603     if (a->isCheckable())
604         a->setChecked(checked);
605 #endif // QT_NO_ACTION
606 }
607 
updateNavigationActions()608 void QWebPagePrivate::updateNavigationActions()
609 {
610     updateAction(QWebPage::Back);
611     updateAction(QWebPage::Forward);
612     updateAction(QWebPage::Stop);
613     updateAction(QWebPage::Reload);
614     updateAction(QWebPage::ReloadAndBypassCache);
615 }
616 
updateEditorActions()617 void QWebPagePrivate::updateEditorActions()
618 {
619     updateAction(QWebPage::Cut);
620     updateAction(QWebPage::Copy);
621     updateAction(QWebPage::Paste);
622     updateAction(QWebPage::MoveToNextChar);
623     updateAction(QWebPage::MoveToPreviousChar);
624     updateAction(QWebPage::MoveToNextWord);
625     updateAction(QWebPage::MoveToPreviousWord);
626     updateAction(QWebPage::MoveToNextLine);
627     updateAction(QWebPage::MoveToPreviousLine);
628     updateAction(QWebPage::MoveToStartOfLine);
629     updateAction(QWebPage::MoveToEndOfLine);
630     updateAction(QWebPage::MoveToStartOfBlock);
631     updateAction(QWebPage::MoveToEndOfBlock);
632     updateAction(QWebPage::MoveToStartOfDocument);
633     updateAction(QWebPage::MoveToEndOfDocument);
634     updateAction(QWebPage::SelectNextChar);
635     updateAction(QWebPage::SelectPreviousChar);
636     updateAction(QWebPage::SelectNextWord);
637     updateAction(QWebPage::SelectPreviousWord);
638     updateAction(QWebPage::SelectNextLine);
639     updateAction(QWebPage::SelectPreviousLine);
640     updateAction(QWebPage::SelectStartOfLine);
641     updateAction(QWebPage::SelectEndOfLine);
642     updateAction(QWebPage::SelectStartOfBlock);
643     updateAction(QWebPage::SelectEndOfBlock);
644     updateAction(QWebPage::SelectStartOfDocument);
645     updateAction(QWebPage::SelectEndOfDocument);
646     updateAction(QWebPage::DeleteStartOfWord);
647     updateAction(QWebPage::DeleteEndOfWord);
648     updateAction(QWebPage::SetTextDirectionDefault);
649     updateAction(QWebPage::SetTextDirectionLeftToRight);
650     updateAction(QWebPage::SetTextDirectionRightToLeft);
651     updateAction(QWebPage::ToggleBold);
652     updateAction(QWebPage::ToggleItalic);
653     updateAction(QWebPage::ToggleUnderline);
654     updateAction(QWebPage::InsertParagraphSeparator);
655     updateAction(QWebPage::InsertLineSeparator);
656     updateAction(QWebPage::PasteAndMatchStyle);
657     updateAction(QWebPage::RemoveFormat);
658     updateAction(QWebPage::ToggleStrikethrough);
659     updateAction(QWebPage::ToggleSubscript);
660     updateAction(QWebPage::ToggleSuperscript);
661     updateAction(QWebPage::InsertUnorderedList);
662     updateAction(QWebPage::InsertOrderedList);
663     updateAction(QWebPage::Indent);
664     updateAction(QWebPage::Outdent);
665     updateAction(QWebPage::AlignCenter);
666     updateAction(QWebPage::AlignJustified);
667     updateAction(QWebPage::AlignLeft);
668     updateAction(QWebPage::AlignRight);
669 }
670 
timerEvent(QTimerEvent * ev)671 void QWebPagePrivate::timerEvent(QTimerEvent *ev)
672 {
673     int timerId = ev->timerId();
674     if (timerId == tripleClickTimer.timerId())
675         tripleClickTimer.stop();
676     else
677         q->timerEvent(ev);
678 }
679 
680 template<class T>
mouseMoveEvent(T * ev)681 void QWebPagePrivate::mouseMoveEvent(T* ev)
682 {
683     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
684     if (!frame->view())
685         return;
686 
687     bool accepted = frame->eventHandler()->mouseMoved(PlatformMouseEvent(ev, 0));
688     ev->setAccepted(accepted);
689 }
690 
691 template<class T>
mousePressEvent(T * ev)692 void QWebPagePrivate::mousePressEvent(T* ev)
693 {
694     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
695     if (!frame->view())
696         return;
697 
698     RefPtr<WebCore::Node> oldNode;
699     Frame* focusedFrame = page->focusController()->focusedFrame();
700     if (Document* focusedDocument = focusedFrame ? focusedFrame->document() : 0)
701         oldNode = focusedDocument->focusedNode();
702 
703     if (tripleClickTimer.isActive()
704             && (ev->pos() - tripleClick).manhattanLength()
705                 < QApplication::startDragDistance()) {
706         mouseTripleClickEvent(ev);
707         return;
708     }
709 
710     bool accepted = false;
711     adjustPointForClicking(ev);
712     PlatformMouseEvent mev(ev, 1);
713     // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
714     if (mev.button() != NoButton)
715         accepted = frame->eventHandler()->handleMousePressEvent(mev);
716     ev->setAccepted(accepted);
717 
718     RefPtr<WebCore::Node> newNode;
719     focusedFrame = page->focusController()->focusedFrame();
720     if (Document* focusedDocument = focusedFrame ? focusedFrame->document() : 0)
721         newNode = focusedDocument->focusedNode();
722 
723     if (newNode && oldNode != newNode)
724         clickCausedFocus = true;
725 }
726 
727 template<class T>
mouseDoubleClickEvent(T * ev)728 void QWebPagePrivate::mouseDoubleClickEvent(T *ev)
729 {
730     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
731     if (!frame->view())
732         return;
733 
734     bool accepted = false;
735     PlatformMouseEvent mev(ev, 2);
736     // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
737     if (mev.button() != NoButton)
738         accepted = frame->eventHandler()->handleMousePressEvent(mev);
739     ev->setAccepted(accepted);
740 
741     tripleClickTimer.start(QApplication::doubleClickInterval(), q);
742     tripleClick = QPointF(ev->pos()).toPoint();
743 }
744 
745 template<class T>
mouseTripleClickEvent(T * ev)746 void QWebPagePrivate::mouseTripleClickEvent(T *ev)
747 {
748     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
749     if (!frame->view())
750         return;
751 
752     bool accepted = false;
753     PlatformMouseEvent mev(ev, 3);
754     // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
755     if (mev.button() != NoButton)
756         accepted = frame->eventHandler()->handleMousePressEvent(mev);
757     ev->setAccepted(accepted);
758 }
759 
handleClipboard(QEvent * ev,Qt::MouseButton button)760 void QWebPagePrivate::handleClipboard(QEvent* ev, Qt::MouseButton button)
761 {
762 #ifndef QT_NO_CLIPBOARD
763     if (QApplication::clipboard()->supportsSelection()) {
764         bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode();
765         Pasteboard::generalPasteboard()->setSelectionMode(true);
766         WebCore::Frame* focusFrame = page->focusController()->focusedOrMainFrame();
767         if (button == Qt::LeftButton) {
768             if (focusFrame && (focusFrame->editor()->canCopy() || focusFrame->editor()->canDHTMLCopy())) {
769                 Pasteboard::generalPasteboard()->writeSelection(focusFrame->editor()->selectedRange().get(), focusFrame->editor()->canSmartCopyOrDelete(), focusFrame);
770                 ev->setAccepted(true);
771             }
772         } else if (button == Qt::MidButton) {
773             if (focusFrame && (focusFrame->editor()->canPaste() || focusFrame->editor()->canDHTMLPaste())) {
774                 focusFrame->editor()->paste();
775                 ev->setAccepted(true);
776             }
777         }
778         Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode);
779     }
780 #endif
781 }
782 
783 template<class T>
mouseReleaseEvent(T * ev)784 void QWebPagePrivate::mouseReleaseEvent(T *ev)
785 {
786     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
787     if (!frame->view())
788         return;
789 
790     bool accepted = false;
791     adjustPointForClicking(ev);
792     PlatformMouseEvent mev(ev, 0);
793     // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
794     if (mev.button() != NoButton)
795         accepted = frame->eventHandler()->handleMouseReleaseEvent(mev);
796     ev->setAccepted(accepted);
797 
798     handleClipboard(ev, ev->button());
799     handleSoftwareInputPanel(ev->button(), QPointF(ev->pos()).toPoint());
800 }
801 
handleSoftwareInputPanel(Qt::MouseButton button,const QPoint & pos)802 void QWebPagePrivate::handleSoftwareInputPanel(Qt::MouseButton button, const QPoint& pos)
803 {
804     Frame* frame = page->focusController()->focusedFrame();
805     if (!frame)
806         return;
807 
808     if (client && client->inputMethodEnabled()
809         && frame->document()->focusedNode()
810         && button == Qt::LeftButton && qApp->autoSipEnabled()) {
811         QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel(
812             client->ownerWidget()->style()->styleHint(QStyle::SH_RequestSoftwareInputPanel));
813         if (!clickCausedFocus || behavior == QStyle::RSIP_OnMouseClick) {
814             HitTestResult result = frame->eventHandler()->hitTestResultAtPoint(frame->view()->windowToContents(pos), false);
815             if (result.isContentEditable()) {
816                 QEvent event(QEvent::RequestSoftwareInputPanel);
817                 QApplication::sendEvent(client->ownerWidget(), &event);
818             }
819         }
820     }
821 
822     clickCausedFocus = false;
823 }
824 
825 #ifndef QT_NO_CONTEXTMENU
contextMenuEvent(const QPoint & globalPos)826 void QWebPagePrivate::contextMenuEvent(const QPoint& globalPos)
827 {
828     QMenu *menu = q->createStandardContextMenu();
829     if (menu) {
830         menu->exec(globalPos);
831         delete menu;
832     }
833 }
834 #endif // QT_NO_CONTEXTMENU
835 
836 /*!
837     \since 4.5
838     This function creates the standard context menu which is shown when
839     the user clicks on the web page with the right mouse button. It is
840     called from the default contextMenuEvent() handler. The popup menu's
841     ownership is transferred to the caller.
842  */
createStandardContextMenu()843 QMenu *QWebPage::createStandardContextMenu()
844 {
845 #ifndef QT_NO_CONTEXTMENU
846     QMenu *menu = d->currentContextMenu;
847     d->currentContextMenu = 0;
848     return menu;
849 #else
850     return 0;
851 #endif
852 }
853 
854 #ifndef QT_NO_WHEELEVENT
855 template<class T>
wheelEvent(T * ev)856 void QWebPagePrivate::wheelEvent(T *ev)
857 {
858     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
859     if (!frame->view())
860         return;
861 
862     WebCore::PlatformWheelEvent pev(ev);
863     bool accepted = frame->eventHandler()->handleWheelEvent(pev);
864     ev->setAccepted(accepted);
865 }
866 #endif // QT_NO_WHEELEVENT
867 
868 #ifndef QT_NO_SHORTCUT
editorActionForKeyEvent(QKeyEvent * event)869 QWebPage::WebAction QWebPagePrivate::editorActionForKeyEvent(QKeyEvent* event)
870 {
871     static struct {
872         QKeySequence::StandardKey standardKey;
873         QWebPage::WebAction action;
874     } editorActions[] = {
875         { QKeySequence::Cut, QWebPage::Cut },
876         { QKeySequence::Copy, QWebPage::Copy },
877         { QKeySequence::Paste, QWebPage::Paste },
878         { QKeySequence::Undo, QWebPage::Undo },
879         { QKeySequence::Redo, QWebPage::Redo },
880         { QKeySequence::MoveToNextChar, QWebPage::MoveToNextChar },
881         { QKeySequence::MoveToPreviousChar, QWebPage::MoveToPreviousChar },
882         { QKeySequence::MoveToNextWord, QWebPage::MoveToNextWord },
883         { QKeySequence::MoveToPreviousWord, QWebPage::MoveToPreviousWord },
884         { QKeySequence::MoveToNextLine, QWebPage::MoveToNextLine },
885         { QKeySequence::MoveToPreviousLine, QWebPage::MoveToPreviousLine },
886         { QKeySequence::MoveToStartOfLine, QWebPage::MoveToStartOfLine },
887         { QKeySequence::MoveToEndOfLine, QWebPage::MoveToEndOfLine },
888         { QKeySequence::MoveToStartOfBlock, QWebPage::MoveToStartOfBlock },
889         { QKeySequence::MoveToEndOfBlock, QWebPage::MoveToEndOfBlock },
890         { QKeySequence::MoveToStartOfDocument, QWebPage::MoveToStartOfDocument },
891         { QKeySequence::MoveToEndOfDocument, QWebPage::MoveToEndOfDocument },
892         { QKeySequence::SelectNextChar, QWebPage::SelectNextChar },
893         { QKeySequence::SelectPreviousChar, QWebPage::SelectPreviousChar },
894         { QKeySequence::SelectNextWord, QWebPage::SelectNextWord },
895         { QKeySequence::SelectPreviousWord, QWebPage::SelectPreviousWord },
896         { QKeySequence::SelectNextLine, QWebPage::SelectNextLine },
897         { QKeySequence::SelectPreviousLine, QWebPage::SelectPreviousLine },
898         { QKeySequence::SelectStartOfLine, QWebPage::SelectStartOfLine },
899         { QKeySequence::SelectEndOfLine, QWebPage::SelectEndOfLine },
900         { QKeySequence::SelectStartOfBlock, QWebPage::SelectStartOfBlock },
901         { QKeySequence::SelectEndOfBlock,  QWebPage::SelectEndOfBlock },
902         { QKeySequence::SelectStartOfDocument, QWebPage::SelectStartOfDocument },
903         { QKeySequence::SelectEndOfDocument, QWebPage::SelectEndOfDocument },
904         { QKeySequence::DeleteStartOfWord, QWebPage::DeleteStartOfWord },
905         { QKeySequence::DeleteEndOfWord, QWebPage::DeleteEndOfWord },
906         { QKeySequence::InsertParagraphSeparator, QWebPage::InsertParagraphSeparator },
907         { QKeySequence::InsertLineSeparator, QWebPage::InsertLineSeparator },
908         { QKeySequence::SelectAll, QWebPage::SelectAll },
909         { QKeySequence::UnknownKey, QWebPage::NoWebAction }
910     };
911 
912     for (int i = 0; editorActions[i].standardKey != QKeySequence::UnknownKey; ++i)
913         if (event == editorActions[i].standardKey)
914             return editorActions[i].action;
915 
916     return QWebPage::NoWebAction;
917 }
918 #endif // QT_NO_SHORTCUT
919 
keyPressEvent(QKeyEvent * ev)920 void QWebPagePrivate::keyPressEvent(QKeyEvent *ev)
921 {
922     bool handled = false;
923     WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
924     // we forward the key event to WebCore first to handle potential DOM
925     // defined event handlers and later on end up in EditorClientQt::handleKeyboardEvent
926     // to trigger editor commands via triggerAction().
927     if (!handled)
928         handled = frame->eventHandler()->keyEvent(ev);
929     if (!handled) {
930         handled = true;
931         if (!handleScrolling(ev, frame)) {
932             switch (ev->key()) {
933             case Qt::Key_Back:
934                 q->triggerAction(QWebPage::Back);
935                 break;
936             case Qt::Key_Forward:
937                 q->triggerAction(QWebPage::Forward);
938                 break;
939             case Qt::Key_Stop:
940                 q->triggerAction(QWebPage::Stop);
941                 break;
942             case Qt::Key_Refresh:
943                 q->triggerAction(QWebPage::Reload);
944                 break;
945             case Qt::Key_Backspace:
946                 if (ev->modifiers() == Qt::ShiftModifier)
947                     q->triggerAction(QWebPage::Forward);
948                 else
949                     q->triggerAction(QWebPage::Back);
950                 break;
951             default:
952                 handled = false;
953                 break;
954             }
955         }
956     }
957 
958     ev->setAccepted(handled);
959 }
960 
keyReleaseEvent(QKeyEvent * ev)961 void QWebPagePrivate::keyReleaseEvent(QKeyEvent *ev)
962 {
963     if (ev->isAutoRepeat()) {
964         ev->setAccepted(true);
965         return;
966     }
967 
968     WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
969     bool handled = frame->eventHandler()->keyEvent(ev);
970     ev->setAccepted(handled);
971 }
972 
focusInEvent(QFocusEvent *)973 void QWebPagePrivate::focusInEvent(QFocusEvent*)
974 {
975     FocusController *focusController = page->focusController();
976     focusController->setActive(true);
977     focusController->setFocused(true);
978     if (!focusController->focusedFrame())
979         focusController->setFocusedFrame(QWebFramePrivate::core(mainFrame));
980 }
981 
focusOutEvent(QFocusEvent *)982 void QWebPagePrivate::focusOutEvent(QFocusEvent*)
983 {
984     // only set the focused frame inactive so that we stop painting the caret
985     // and the focus frame. But don't tell the focus controller so that upon
986     // focusInEvent() we can re-activate the frame.
987     FocusController *focusController = page->focusController();
988     // Call setFocused first so that window.onblur doesn't get called twice
989     focusController->setFocused(false);
990     focusController->setActive(false);
991 }
992 
993 template<class T>
dragEnterEvent(T * ev)994 void QWebPagePrivate::dragEnterEvent(T* ev)
995 {
996 #ifndef QT_NO_DRAGANDDROP
997     DragData dragData(ev->mimeData(), QPointF(ev->pos()).toPoint(),
998             QCursor::pos(), dropActionToDragOp(ev->possibleActions()));
999     Qt::DropAction action = dragOpToDropAction(page->dragController()->dragEntered(&dragData));
1000     ev->setDropAction(action);
1001     ev->acceptProposedAction();
1002 #endif
1003 }
1004 
1005 template<class T>
dragLeaveEvent(T * ev)1006 void QWebPagePrivate::dragLeaveEvent(T *ev)
1007 {
1008 #ifndef QT_NO_DRAGANDDROP
1009     DragData dragData(0, IntPoint(), QCursor::pos(), DragOperationNone);
1010     page->dragController()->dragExited(&dragData);
1011     ev->accept();
1012 #endif
1013 }
1014 
1015 template<class T>
dragMoveEvent(T * ev)1016 void QWebPagePrivate::dragMoveEvent(T *ev)
1017 {
1018 #ifndef QT_NO_DRAGANDDROP
1019     DragData dragData(ev->mimeData(), QPointF(ev->pos()).toPoint(),
1020             QCursor::pos(), dropActionToDragOp(ev->possibleActions()));
1021     m_lastDropAction = dragOpToDropAction(page->dragController()->dragUpdated(&dragData));
1022     ev->setDropAction(m_lastDropAction);
1023     if (m_lastDropAction != Qt::IgnoreAction)
1024         ev->accept();
1025 #endif
1026 }
1027 
1028 template<class T>
dropEvent(T * ev)1029 void QWebPagePrivate::dropEvent(T *ev)
1030 {
1031 #ifndef QT_NO_DRAGANDDROP
1032     DragData dragData(ev->mimeData(), QPointF(ev->pos()).toPoint(),
1033             QCursor::pos(), dropActionToDragOp(ev->possibleActions()));
1034     if (page->dragController()->performDrag(&dragData)) {
1035         ev->setDropAction(m_lastDropAction);
1036         ev->accept();
1037     }
1038 #endif
1039 }
1040 
leaveEvent(QEvent *)1041 void QWebPagePrivate::leaveEvent(QEvent*)
1042 {
1043     // Fake a mouse move event just outside of the widget, since all
1044     // the interesting mouse-out behavior like invalidating scrollbars
1045     // is handled by the WebKit event handler's mouseMoved function.
1046     QMouseEvent fakeEvent(QEvent::MouseMove, QCursor::pos(), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
1047     mouseMoveEvent(&fakeEvent);
1048 }
1049 
1050 /*!
1051     \property QWebPage::palette
1052     \brief the page's palette
1053 
1054     The base brush of the palette is used to draw the background of the main frame.
1055 
1056     By default, this property contains the application's default palette.
1057 */
setPalette(const QPalette & pal)1058 void QWebPage::setPalette(const QPalette &pal)
1059 {
1060     d->palette = pal;
1061     if (!d->mainFrame || !d->mainFrame->d->frame->view())
1062         return;
1063 
1064     QBrush brush = pal.brush(QPalette::Base);
1065     QColor backgroundColor = brush.style() == Qt::SolidPattern ? brush.color() : QColor();
1066     QWebFramePrivate::core(d->mainFrame)->view()->updateBackgroundRecursively(backgroundColor, !backgroundColor.alpha());
1067 }
1068 
palette() const1069 QPalette QWebPage::palette() const
1070 {
1071     return d->palette;
1072 }
1073 
inputMethodEvent(QInputMethodEvent * ev)1074 void QWebPagePrivate::inputMethodEvent(QInputMethodEvent *ev)
1075 {
1076     WebCore::Frame *frame = page->focusController()->focusedOrMainFrame();
1077     WebCore::Editor *editor = frame->editor();
1078 
1079     if (!editor->canEdit()) {
1080         ev->ignore();
1081         return;
1082     }
1083 
1084     Node* node = 0;
1085     if (frame->selection()->rootEditableElement())
1086         node = frame->selection()->rootEditableElement()->shadowAncestorNode();
1087 
1088     Vector<CompositionUnderline> underlines;
1089     bool hasSelection = false;
1090 
1091     for (int i = 0; i < ev->attributes().size(); ++i) {
1092         const QInputMethodEvent::Attribute& a = ev->attributes().at(i);
1093         switch (a.type) {
1094         case QInputMethodEvent::TextFormat: {
1095             QTextCharFormat textCharFormat = a.value.value<QTextFormat>().toCharFormat();
1096             QColor qcolor = textCharFormat.underlineColor();
1097             underlines.append(CompositionUnderline(qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length)), Color(makeRGBA(qcolor.red(), qcolor.green(), qcolor.blue(), qcolor.alpha())), false));
1098             break;
1099         }
1100         case QInputMethodEvent::Cursor: {
1101             frame->selection()->setCaretVisible(a.length); //if length is 0 cursor is invisible
1102             if (a.length > 0) {
1103                 RenderObject* caretRenderer = frame->selection()->caretRenderer();
1104                 if (caretRenderer) {
1105                     QColor qcolor = a.value.value<QColor>();
1106                     caretRenderer->style()->setColor(Color(makeRGBA(qcolor.red(), qcolor.green(), qcolor.blue(), qcolor.alpha())));
1107                 }
1108             }
1109             break;
1110         }
1111         case QInputMethodEvent::Selection: {
1112             hasSelection = true;
1113             // A selection in the inputMethodEvent is always reflected in the visible text
1114             if (node)
1115                 setSelectionRange(node, qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length)));
1116 
1117             if (!ev->preeditString().isEmpty())
1118                 editor->setComposition(ev->preeditString(), underlines, qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length)));
1119             else {
1120                 // If we are in the middle of a composition, an empty pre-edit string and a selection of zero
1121                 // cancels the current composition
1122                 if (editor->hasComposition() && (a.start + a.length == 0))
1123                     editor->setComposition(QString(), underlines, 0, 0);
1124             }
1125             break;
1126         }
1127         default:
1128             break;
1129         }
1130     }
1131 
1132     if (node && ev->replacementLength() > 0) {
1133         int cursorPos = frame->selection()->extent().offsetInContainerNode();
1134         int start = cursorPos + ev->replacementStart();
1135         setSelectionRange(node, start, start + ev->replacementLength());
1136         // Commit regardless of whether commitString is empty, to get rid of selection.
1137         editor->confirmComposition(ev->commitString());
1138     } else if (!ev->commitString().isEmpty()) {
1139         if (editor->hasComposition())
1140             editor->confirmComposition(ev->commitString());
1141         else
1142             editor->insertText(ev->commitString(), 0);
1143     } else if (!hasSelection && !ev->preeditString().isEmpty())
1144         editor->setComposition(ev->preeditString(), underlines, 0, 0);
1145     else if (ev->preeditString().isEmpty() && editor->hasComposition())
1146         editor->confirmComposition(String());
1147 
1148     ev->accept();
1149 }
1150 
1151 #ifndef QT_NO_PROPERTIES
1152 typedef struct {
1153     const char* name;
1154     double deferredRepaintDelay;
1155     double initialDeferredRepaintDelayDuringLoading;
1156     double maxDeferredRepaintDelayDuringLoading;
1157     double deferredRepaintDelayIncrementDuringLoading;
1158 } QRepaintThrottlingPreset;
1159 
dynamicPropertyChangeEvent(QDynamicPropertyChangeEvent * event)1160 void QWebPagePrivate::dynamicPropertyChangeEvent(QDynamicPropertyChangeEvent* event)
1161 {
1162     if (event->propertyName() == "_q_viewMode") {
1163         page->setViewMode(Page::stringToViewMode(q->property("_q_viewMode").toString()));
1164     } else if (event->propertyName() == "_q_HTMLTokenizerChunkSize") {
1165         int chunkSize = q->property("_q_HTMLTokenizerChunkSize").toInt();
1166         q->handle()->page->setCustomHTMLTokenizerChunkSize(chunkSize);
1167     } else if (event->propertyName() == "_q_HTMLTokenizerTimeDelay") {
1168         double timeDelay = q->property("_q_HTMLTokenizerTimeDelay").toDouble();
1169         q->handle()->page->setCustomHTMLTokenizerTimeDelay(timeDelay);
1170     } else if (event->propertyName() == "_q_RepaintThrottlingDeferredRepaintDelay") {
1171         double p = q->property("_q_RepaintThrottlingDeferredRepaintDelay").toDouble();
1172         FrameView::setRepaintThrottlingDeferredRepaintDelay(p);
1173     } else if (event->propertyName() == "_q_RepaintThrottlingnInitialDeferredRepaintDelayDuringLoading") {
1174         double p = q->property("_q_RepaintThrottlingnInitialDeferredRepaintDelayDuringLoading").toDouble();
1175         FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(p);
1176     } else if (event->propertyName() == "_q_RepaintThrottlingMaxDeferredRepaintDelayDuringLoading") {
1177         double p = q->property("_q_RepaintThrottlingMaxDeferredRepaintDelayDuringLoading").toDouble();
1178         FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(p);
1179     } else if (event->propertyName() == "_q_RepaintThrottlingDeferredRepaintDelayIncrementDuringLoading") {
1180         double p = q->property("_q_RepaintThrottlingDeferredRepaintDelayIncrementDuringLoading").toDouble();
1181         FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(p);
1182     } else if (event->propertyName() == "_q_RepaintThrottlingPreset") {
1183         static const QRepaintThrottlingPreset presets[] = {
1184             {   "NoThrottling",     0,      0,      0,      0 },
1185             {   "Legacy",       0.025,      0,    2.5,    0.5 },
1186             {   "Minimal",       0.01,      0,      1,    0.2 },
1187             {   "Medium",       0.025,      1,      5,    0.5 },
1188             {   "Heavy",          0.1,      2,     10,      1 }
1189         };
1190 
1191         QString p = q->property("_q_RepaintThrottlingPreset").toString();
1192         for (size_t i = 0; i < sizeof(presets) / sizeof(presets[0]); i++) {
1193             if (p == QLatin1String(presets[i].name)) {
1194                 FrameView::setRepaintThrottlingDeferredRepaintDelay(
1195                         presets[i].deferredRepaintDelay);
1196                 FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(
1197                         presets[i].initialDeferredRepaintDelayDuringLoading);
1198                 FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(
1199                         presets[i].maxDeferredRepaintDelayDuringLoading);
1200                 FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(
1201                         presets[i].deferredRepaintDelayIncrementDuringLoading);
1202                 break;
1203             }
1204         }
1205     }
1206 #if ENABLE(TILED_BACKING_STORE)
1207     else if (event->propertyName() == "_q_TiledBackingStoreTileSize") {
1208         WebCore::Frame* frame = QWebFramePrivate::core(q->mainFrame());
1209         if (!frame->tiledBackingStore())
1210             return;
1211         QSize tileSize = q->property("_q_TiledBackingStoreTileSize").toSize();
1212         frame->tiledBackingStore()->setTileSize(tileSize);
1213     } else if (event->propertyName() == "_q_TiledBackingStoreTileCreationDelay") {
1214         WebCore::Frame* frame = QWebFramePrivate::core(q->mainFrame());
1215         if (!frame->tiledBackingStore())
1216             return;
1217         int tileCreationDelay = q->property("_q_TiledBackingStoreTileCreationDelay").toInt();
1218         frame->tiledBackingStore()->setTileCreationDelay(static_cast<double>(tileCreationDelay) / 1000.);
1219     } else if (event->propertyName() == "_q_TiledBackingStoreKeepAreaMultiplier") {
1220         WebCore::Frame* frame = QWebFramePrivate::core(q->mainFrame());
1221         if (!frame->tiledBackingStore())
1222             return;
1223         FloatSize keepMultiplier;
1224         FloatSize coverMultiplier;
1225         frame->tiledBackingStore()->getKeepAndCoverAreaMultipliers(keepMultiplier, coverMultiplier);
1226         QSizeF qSize = q->property("_q_TiledBackingStoreKeepAreaMultiplier").toSizeF();
1227         keepMultiplier = FloatSize(qSize.width(), qSize.height());
1228         frame->tiledBackingStore()->setKeepAndCoverAreaMultipliers(keepMultiplier, coverMultiplier);
1229     } else if (event->propertyName() == "_q_TiledBackingStoreCoverAreaMultiplier") {
1230         WebCore::Frame* frame = QWebFramePrivate::core(q->mainFrame());
1231         if (!frame->tiledBackingStore())
1232             return;
1233         FloatSize keepMultiplier;
1234         FloatSize coverMultiplier;
1235         frame->tiledBackingStore()->getKeepAndCoverAreaMultipliers(keepMultiplier, coverMultiplier);
1236         QSizeF qSize = q->property("_q_TiledBackingStoreCoverAreaMultiplier").toSizeF();
1237         coverMultiplier = FloatSize(qSize.width(), qSize.height());
1238         frame->tiledBackingStore()->setKeepAndCoverAreaMultipliers(keepMultiplier, coverMultiplier);
1239     }
1240 #endif
1241     else if (event->propertyName() == "_q_webInspectorServerPort") {
1242         InspectorServerQt* inspectorServer = InspectorServerQt::server();
1243         inspectorServer->listen(inspectorServerPort());
1244     } else if (event->propertyName() == "_q_deadDecodedDataDeletionInterval") {
1245         double interval = q->property("_q_deadDecodedDataDeletionInterval").toDouble();
1246         memoryCache()->setDeadDecodedDataDeletionInterval(interval);
1247     }
1248 }
1249 #endif
1250 
shortcutOverrideEvent(QKeyEvent * event)1251 void QWebPagePrivate::shortcutOverrideEvent(QKeyEvent* event)
1252 {
1253     WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
1254     WebCore::Editor* editor = frame->editor();
1255     if (editor->canEdit()) {
1256         if (event->modifiers() == Qt::NoModifier
1257             || event->modifiers() == Qt::ShiftModifier
1258             || event->modifiers() == Qt::KeypadModifier) {
1259                 if (event->key() < Qt::Key_Escape) {
1260                     event->accept();
1261                 } else {
1262                     switch (event->key()) {
1263                     case Qt::Key_Return:
1264                     case Qt::Key_Enter:
1265                     case Qt::Key_Delete:
1266                     case Qt::Key_Home:
1267                     case Qt::Key_End:
1268                     case Qt::Key_Backspace:
1269                     case Qt::Key_Left:
1270                     case Qt::Key_Right:
1271                     case Qt::Key_Up:
1272                     case Qt::Key_Down:
1273                     case Qt::Key_Tab:
1274                         event->accept();
1275                     default:
1276                         break;
1277                     }
1278                 }
1279         }
1280 #ifndef QT_NO_SHORTCUT
1281         else if (editorActionForKeyEvent(event) != QWebPage::NoWebAction)
1282             event->accept();
1283 #endif
1284     }
1285 }
1286 
handleScrolling(QKeyEvent * ev,Frame * frame)1287 bool QWebPagePrivate::handleScrolling(QKeyEvent *ev, Frame *frame)
1288 {
1289     ScrollDirection direction;
1290     ScrollGranularity granularity;
1291 
1292 #ifndef QT_NO_SHORTCUT
1293     if (ev == QKeySequence::MoveToNextPage
1294         || (ev->key() == Qt::Key_Space && !(ev->modifiers() & Qt::ShiftModifier))) {
1295         granularity = ScrollByPage;
1296         direction = ScrollDown;
1297     } else if (ev == QKeySequence::MoveToPreviousPage
1298                || ((ev->key() == Qt::Key_Space) && (ev->modifiers() & Qt::ShiftModifier))) {
1299         granularity = ScrollByPage;
1300         direction = ScrollUp;
1301     } else
1302 #endif // QT_NO_SHORTCUT
1303     if ((ev->key() == Qt::Key_Up && ev->modifiers() & Qt::ControlModifier)
1304                || ev->key() == Qt::Key_Home) {
1305         granularity = ScrollByDocument;
1306         direction = ScrollUp;
1307     } else if ((ev->key() == Qt::Key_Down && ev->modifiers() & Qt::ControlModifier)
1308                || ev->key() == Qt::Key_End) {
1309         granularity = ScrollByDocument;
1310         direction = ScrollDown;
1311     } else {
1312         switch (ev->key()) {
1313             case Qt::Key_Up:
1314                 granularity = ScrollByLine;
1315                 direction = ScrollUp;
1316                 break;
1317             case Qt::Key_Down:
1318                 granularity = ScrollByLine;
1319                 direction = ScrollDown;
1320                 break;
1321             case Qt::Key_Left:
1322                 granularity = ScrollByLine;
1323                 direction = ScrollLeft;
1324                 break;
1325             case Qt::Key_Right:
1326                 granularity = ScrollByLine;
1327                 direction = ScrollRight;
1328                 break;
1329             default:
1330                 return false;
1331         }
1332     }
1333 
1334     return frame->eventHandler()->scrollRecursively(direction, granularity);
1335 }
1336 
adjustPointForClicking(QMouseEvent *)1337 void QWebPagePrivate::adjustPointForClicking(QMouseEvent*)
1338 {
1339     notImplemented();
1340 }
1341 
1342 #if !defined(QT_NO_GRAPHICSVIEW)
adjustPointForClicking(QGraphicsSceneMouseEvent * ev)1343 void QWebPagePrivate::adjustPointForClicking(QGraphicsSceneMouseEvent* ev)
1344 {
1345     QtPlatformPlugin platformPlugin;
1346     OwnPtr<QWebTouchModifier> touchModifier = platformPlugin.createTouchModifier();
1347     if (!touchModifier)
1348         return;
1349 
1350     unsigned topPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Up);
1351     unsigned rightPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Right);
1352     unsigned bottomPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Down);
1353     unsigned leftPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Left);
1354 
1355     touchModifier = nullptr;
1356 
1357     if (!topPadding && !rightPadding && !bottomPadding && !leftPadding)
1358         return;
1359 
1360     Document* startingDocument = page->mainFrame()->document();
1361     if (!startingDocument)
1362         return;
1363 
1364     IntPoint originalPoint(QPointF(ev->pos()).toPoint());
1365     TouchAdjuster touchAdjuster(topPadding, rightPadding, bottomPadding, leftPadding);
1366     IntPoint adjustedPoint = touchAdjuster.findCandidatePointForTouch(originalPoint, startingDocument);
1367     if (adjustedPoint == IntPoint::zero())
1368         return;
1369 
1370     ev->setPos(QPointF(adjustedPoint));
1371 }
1372 #endif
1373 
touchEvent(QTouchEvent * event)1374 bool QWebPagePrivate::touchEvent(QTouchEvent* event)
1375 {
1376 #if ENABLE(TOUCH_EVENTS)
1377     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
1378     if (!frame->view())
1379         return false;
1380 
1381     // Always accept the QTouchEvent so that we'll receive also TouchUpdate and TouchEnd events
1382     event->setAccepted(true);
1383 
1384     // Return whether the default action was cancelled in the JS event handler
1385     return frame->eventHandler()->handleTouchEvent(PlatformTouchEvent(event));
1386 #else
1387     event->ignore();
1388     return false;
1389 #endif
1390 }
1391 
1392 /*!
1393   This method is used by the input method to query a set of properties of the page
1394   to be able to support complex input method operations as support for surrounding
1395   text and reconversions.
1396 
1397   \a property specifies which property is queried.
1398 
1399   \sa QWidget::inputMethodEvent(), QInputMethodEvent, QInputContext
1400 */
inputMethodQuery(Qt::InputMethodQuery property) const1401 QVariant QWebPage::inputMethodQuery(Qt::InputMethodQuery property) const
1402 {
1403     Frame* frame = d->page->focusController()->focusedFrame();
1404     if (!frame)
1405         return QVariant();
1406 
1407     WebCore::Editor* editor = frame->editor();
1408 
1409     RenderObject* renderer = 0;
1410     RenderTextControl* renderTextControl = 0;
1411 
1412     if (frame->selection()->rootEditableElement())
1413         renderer = frame->selection()->rootEditableElement()->shadowAncestorNode()->renderer();
1414 
1415     if (renderer && renderer->isTextControl())
1416         renderTextControl = toRenderTextControl(renderer);
1417 
1418     switch (property) {
1419         case Qt::ImMicroFocus: {
1420             WebCore::FrameView* view = frame->view();
1421             if (view && view->needsLayout()) {
1422                 // We can't access absoluteCaretBounds() while the view needs to layout.
1423                 return QVariant();
1424             }
1425             return QVariant(view->contentsToWindow(frame->selection()->absoluteCaretBounds()));
1426         }
1427         case Qt::ImFont: {
1428             if (renderTextControl) {
1429                 RenderStyle* renderStyle = renderTextControl->style();
1430                 return QVariant(QFont(renderStyle->font().font()));
1431             }
1432             return QVariant(QFont());
1433         }
1434         case Qt::ImCursorPosition: {
1435             if (editor->hasComposition())
1436                 return QVariant(frame->selection()->end().offsetInContainerNode());
1437             return QVariant(frame->selection()->extent().offsetInContainerNode());
1438         }
1439         case Qt::ImSurroundingText: {
1440             if (renderTextControl) {
1441                 QString text = renderTextControl->text();
1442                 RefPtr<Range> range = editor->compositionRange();
1443                 if (range)
1444                     text.remove(range->startPosition().offsetInContainerNode(), TextIterator::rangeLength(range.get()));
1445                 return QVariant(text);
1446             }
1447             return QVariant();
1448         }
1449         case Qt::ImCurrentSelection: {
1450             if (!editor->hasComposition() && renderTextControl) {
1451                 int start = frame->selection()->start().offsetInContainerNode();
1452                 int end = frame->selection()->end().offsetInContainerNode();
1453                 if (end > start)
1454                     return QVariant(QString(renderTextControl->text()).mid(start, end - start));
1455             }
1456             return QVariant();
1457 
1458         }
1459         case Qt::ImAnchorPosition: {
1460             if (editor->hasComposition())
1461                 return QVariant(frame->selection()->start().offsetInContainerNode());
1462             return QVariant(frame->selection()->base().offsetInContainerNode());
1463         }
1464         case Qt::ImMaximumTextLength: {
1465             if (frame->selection()->isContentEditable()) {
1466                 if (frame->document() && frame->document()->focusedNode()) {
1467                     if (frame->document()->focusedNode()->hasTagName(HTMLNames::inputTag)) {
1468                         HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(frame->document()->focusedNode());
1469                         return QVariant(inputElement->maxLength());
1470                     }
1471                 }
1472                 return QVariant(InputElement::s_maximumLength);
1473             }
1474             return QVariant(0);
1475         }
1476         default:
1477             return QVariant();
1478     }
1479 }
1480 
1481 /*!
1482     \internal
1483 */
setInspector(QWebInspector * insp)1484 void QWebPagePrivate::setInspector(QWebInspector* insp)
1485 {
1486     if (inspector)
1487         inspector->d->setFrontend(0);
1488 
1489     if (inspectorIsInternalOnly) {
1490         QWebInspector* inspToDelete = inspector;
1491         inspector = 0;
1492         inspectorIsInternalOnly = false;
1493         delete inspToDelete;    // Delete after to prevent infinite recursion
1494     }
1495 
1496     inspector = insp;
1497 
1498     // Give inspector frontend web view if previously created
1499     if (inspector && inspectorFrontend)
1500         inspector->d->setFrontend(inspectorFrontend);
1501 }
1502 
1503 /*!
1504     \internal
1505     Returns the inspector and creates it if it wasn't created yet.
1506     The instance created here will not be available through QWebPage's API.
1507 */
getOrCreateInspector()1508 QWebInspector* QWebPagePrivate::getOrCreateInspector()
1509 {
1510 #if ENABLE(INSPECTOR)
1511     if (!inspector) {
1512         QWebInspector* insp = new QWebInspector;
1513         insp->setPage(q);
1514         inspectorIsInternalOnly = true;
1515 
1516         Q_ASSERT(inspector); // Associated through QWebInspector::setPage(q)
1517     }
1518 #endif
1519     return inspector;
1520 }
1521 
1522 /*! \internal */
inspectorController()1523 InspectorController* QWebPagePrivate::inspectorController()
1524 {
1525 #if ENABLE(INSPECTOR)
1526     return page->inspectorController();
1527 #else
1528     return 0;
1529 #endif
1530 }
1531 
inspectorServerPort()1532 quint16 QWebPagePrivate::inspectorServerPort()
1533 {
1534 #if ENABLE(INSPECTOR) && !defined(QT_NO_PROPERTIES)
1535     if (q && q->property("_q_webInspectorServerPort").isValid())
1536         return q->property("_q_webInspectorServerPort").toInt();
1537 #endif
1538     return 0;
1539 }
1540 
hasMouseListener(Element * element)1541 static bool hasMouseListener(Element* element)
1542 {
1543     ASSERT(element);
1544     return element->hasEventListeners(eventNames().clickEvent)
1545         || element->hasEventListeners(eventNames().mousedownEvent)
1546         || element->hasEventListeners(eventNames().mouseupEvent);
1547 }
1548 
isClickableElement(Element * element,RefPtr<NodeList> list)1549 static bool isClickableElement(Element* element, RefPtr<NodeList> list)
1550 {
1551     ASSERT(element);
1552     bool isClickable = hasMouseListener(element);
1553     if (!isClickable && list) {
1554         Element* parent = element->parentElement();
1555         unsigned count = list->length();
1556         for (unsigned i = 0; i < count && parent; i++) {
1557             if (list->item(i) != parent)
1558                 continue;
1559 
1560             isClickable = hasMouseListener(parent);
1561             if (isClickable)
1562                 break;
1563 
1564             parent = parent->parentElement();
1565         }
1566     }
1567 
1568     ExceptionCode ec = 0;
1569     return isClickable
1570         || element->webkitMatchesSelector("a,*:link,*:visited,*[role=button],button,input,select,label", ec)
1571         || computedStyle(element)->getPropertyValue(cssPropertyID("cursor")) == "pointer";
1572 }
1573 
isValidFrameOwner(Element * element)1574 static bool isValidFrameOwner(Element* element)
1575 {
1576     ASSERT(element);
1577     return element->isFrameOwnerElement() && static_cast<HTMLFrameOwnerElement*>(element)->contentFrame();
1578 }
1579 
nodeToElement(Node * node)1580 static Element* nodeToElement(Node* node)
1581 {
1582     if (node && node->isElementNode())
1583         return static_cast<Element*>(node);
1584     return 0;
1585 }
1586 
TouchAdjuster(unsigned topPadding,unsigned rightPadding,unsigned bottomPadding,unsigned leftPadding)1587 QWebPagePrivate::TouchAdjuster::TouchAdjuster(unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
1588     : m_topPadding(topPadding)
1589     , m_rightPadding(rightPadding)
1590     , m_bottomPadding(bottomPadding)
1591     , m_leftPadding(leftPadding)
1592 {
1593 }
1594 
findCandidatePointForTouch(const IntPoint & touchPoint,Document * document) const1595 IntPoint QWebPagePrivate::TouchAdjuster::findCandidatePointForTouch(const IntPoint& touchPoint, Document* document) const
1596 {
1597     if (!document)
1598         return IntPoint();
1599 
1600     int x = touchPoint.x();
1601     int y = touchPoint.y();
1602 
1603     RefPtr<NodeList> intersectedNodes = document->nodesFromRect(x, y, m_topPadding, m_rightPadding, m_bottomPadding, m_leftPadding, false);
1604     if (!intersectedNodes)
1605         return IntPoint();
1606 
1607     Element* closestClickableElement = 0;
1608     IntRect largestIntersectionRect;
1609     FrameView* view = document->frame()->view();
1610 
1611     // Touch rect in contents coordinates.
1612     IntRect touchRect(HitTestResult::rectForPoint(view->windowToContents(IntPoint(x, y)), m_topPadding, m_rightPadding, m_bottomPadding, m_leftPadding));
1613 
1614     // Iterate over the list of nodes hit looking for the one whose bounding area
1615     // has largest intersection with the touch area (point + padding).
1616     for (unsigned i = 0; i < intersectedNodes->length(); i++) {
1617         Node* currentNode = intersectedNodes->item(i);
1618 
1619         Element* currentElement = nodeToElement(currentNode);
1620         if (!currentElement || (!isClickableElement(currentElement, 0) && !isValidFrameOwner(currentElement)))
1621             continue;
1622 
1623         IntRect currentElementBoundingRect = currentElement->getRect();
1624         currentElementBoundingRect.intersect(touchRect);
1625 
1626         if (currentElementBoundingRect.isEmpty())
1627             continue;
1628 
1629         int currentIntersectionRectArea = currentElementBoundingRect.width() * currentElementBoundingRect.height();
1630         int largestIntersectionRectArea = largestIntersectionRect.width() * largestIntersectionRect.height();
1631         if (currentIntersectionRectArea > largestIntersectionRectArea) {
1632             closestClickableElement = currentElement;
1633             largestIntersectionRect = currentElementBoundingRect;
1634         }
1635     }
1636 
1637     if (largestIntersectionRect.isEmpty())
1638         return IntPoint();
1639 
1640     // Handle the case when user taps a inner frame. It is done in three steps:
1641     // 1) Transform the original touch point to the inner document coordinates;
1642     // 1) Call nodesFromRect for the inner document in case;
1643     // 3) Re-add the inner frame offset (location) before passing the new clicking
1644     //    position to WebCore.
1645     if (closestClickableElement->isFrameOwnerElement()) {
1646         // Adjust client coordinates' origin to be top left of inner frame viewport.
1647         PassRefPtr<ClientRect> rect = closestClickableElement->getBoundingClientRect();
1648         IntPoint newTouchPoint = touchPoint;
1649         IntSize offset =  IntSize(rect->left(), rect->top());
1650         newTouchPoint -= offset;
1651 
1652         HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(closestClickableElement);
1653         Document* childDocument = owner->contentFrame()->document();
1654         return findCandidatePointForTouch(newTouchPoint, childDocument);
1655     }
1656     return view->contentsToWindow(largestIntersectionRect).center();
1657 }
1658 
1659 /*!
1660    \enum QWebPage::FindFlag
1661 
1662    This enum describes the options available to the findText() function. The options
1663    can be OR-ed together from the following list:
1664 
1665    \value FindBackward Searches backwards instead of forwards.
1666    \value FindCaseSensitively By default findText() works case insensitive. Specifying this option
1667    changes the behaviour to a case sensitive find operation.
1668    \value FindWrapsAroundDocument Makes findText() restart from the beginning of the document if the end
1669    was reached and the text was not found.
1670    \value HighlightAllOccurrences Highlights all existing occurrences of a specific string. (This value was introduced in 4.6.)
1671 */
1672 
1673 /*!
1674     \enum QWebPage::LinkDelegationPolicy
1675 
1676     This enum defines the delegation policies a webpage can have when activating links and emitting
1677     the linkClicked() signal.
1678 
1679     \value DontDelegateLinks No links are delegated. Instead, QWebPage tries to handle them all.
1680     \value DelegateExternalLinks When activating links that point to documents not stored on the
1681     local filesystem or an equivalent - such as the Qt resource system - then linkClicked() is emitted.
1682     \value DelegateAllLinks Whenever a link is activated the linkClicked() signal is emitted.
1683 
1684     \sa QWebPage::linkDelegationPolicy
1685 */
1686 
1687 /*!
1688     \enum QWebPage::NavigationType
1689 
1690     This enum describes the types of navigation available when browsing through hyperlinked
1691     documents.
1692 
1693     \value NavigationTypeLinkClicked The user clicked on a link or pressed return on a focused link.
1694     \value NavigationTypeFormSubmitted The user activated a submit button for an HTML form.
1695     \value NavigationTypeBackOrForward Navigation to a previously shown document in the back or forward history is requested.
1696     \value NavigationTypeReload The user activated the reload action.
1697     \value NavigationTypeFormResubmitted An HTML form was submitted a second time.
1698     \value NavigationTypeOther A navigation to another document using a method not listed above.
1699 
1700     \sa acceptNavigationRequest()
1701 */
1702 
1703 /*!
1704     \enum QWebPage::WebAction
1705 
1706     This enum describes the types of action which can be performed on the web page.
1707 
1708     Actions only have an effect when they are applicable. The availability of
1709     actions can be be determined by checking \l{QAction::}{isEnabled()} on the
1710     action returned by action().
1711 
1712     One method of enabling the text editing, cursor movement, and text selection actions
1713     is by setting \l contentEditable to true.
1714 
1715     \value NoWebAction No action is triggered.
1716     \value OpenLink Open the current link.
1717     \value OpenLinkInNewWindow Open the current link in a new window.
1718     \value OpenFrameInNewWindow Replicate the current frame in a new window.
1719     \value DownloadLinkToDisk Download the current link to the disk.
1720     \value CopyLinkToClipboard Copy the current link to the clipboard.
1721     \value OpenImageInNewWindow Open the highlighted image in a new window.
1722     \value DownloadImageToDisk Download the highlighted image to the disk.
1723     \value CopyImageToClipboard Copy the highlighted image to the clipboard.
1724     \value CopyImageUrlToClipboard Copy the highlighted image's URL to the clipboard.
1725     \value Back Navigate back in the history of navigated links.
1726     \value Forward Navigate forward in the history of navigated links.
1727     \value Stop Stop loading the current page.
1728     \value StopScheduledPageRefresh Stop all pending page refresh/redirect requests.
1729     \value Reload Reload the current page.
1730     \value ReloadAndBypassCache Reload the current page, but do not use any local cache. (Added in Qt 4.6)
1731     \value Cut Cut the content currently selected into the clipboard.
1732     \value Copy Copy the content currently selected into the clipboard.
1733     \value Paste Paste content from the clipboard.
1734     \value Undo Undo the last editing action.
1735     \value Redo Redo the last editing action.
1736     \value MoveToNextChar Move the cursor to the next character.
1737     \value MoveToPreviousChar Move the cursor to the previous character.
1738     \value MoveToNextWord Move the cursor to the next word.
1739     \value MoveToPreviousWord Move the cursor to the previous word.
1740     \value MoveToNextLine Move the cursor to the next line.
1741     \value MoveToPreviousLine Move the cursor to the previous line.
1742     \value MoveToStartOfLine Move the cursor to the start of the line.
1743     \value MoveToEndOfLine Move the cursor to the end of the line.
1744     \value MoveToStartOfBlock Move the cursor to the start of the block.
1745     \value MoveToEndOfBlock Move the cursor to the end of the block.
1746     \value MoveToStartOfDocument Move the cursor to the start of the document.
1747     \value MoveToEndOfDocument Move the cursor to the end of the document.
1748     \value SelectNextChar Select to the next character.
1749     \value SelectPreviousChar Select to the previous character.
1750     \value SelectNextWord Select to the next word.
1751     \value SelectPreviousWord Select to the previous word.
1752     \value SelectNextLine Select to the next line.
1753     \value SelectPreviousLine Select to the previous line.
1754     \value SelectStartOfLine Select to the start of the line.
1755     \value SelectEndOfLine Select to the end of the line.
1756     \value SelectStartOfBlock Select to the start of the block.
1757     \value SelectEndOfBlock Select to the end of the block.
1758     \value SelectStartOfDocument Select to the start of the document.
1759     \value SelectEndOfDocument Select to the end of the document.
1760     \value DeleteStartOfWord Delete to the start of the word.
1761     \value DeleteEndOfWord Delete to the end of the word.
1762     \value SetTextDirectionDefault Set the text direction to the default direction.
1763     \value SetTextDirectionLeftToRight Set the text direction to left-to-right.
1764     \value SetTextDirectionRightToLeft Set the text direction to right-to-left.
1765     \value ToggleBold Toggle the formatting between bold and normal weight.
1766     \value ToggleItalic Toggle the formatting between italic and normal style.
1767     \value ToggleUnderline Toggle underlining.
1768     \value InspectElement Show the Web Inspector with the currently highlighted HTML element.
1769     \value InsertParagraphSeparator Insert a new paragraph.
1770     \value InsertLineSeparator Insert a new line.
1771     \value SelectAll Selects all content.
1772     \value PasteAndMatchStyle Paste content from the clipboard with current style.
1773     \value RemoveFormat Removes formatting and style.
1774     \value ToggleStrikethrough Toggle the formatting between strikethrough and normal style.
1775     \value ToggleSubscript Toggle the formatting between subscript and baseline.
1776     \value ToggleSuperscript Toggle the formatting between supercript and baseline.
1777     \value InsertUnorderedList Toggles the selection between an ordered list and a normal block.
1778     \value InsertOrderedList Toggles the selection between an ordered list and a normal block.
1779     \value Indent Increases the indentation of the currently selected format block by one increment.
1780     \value Outdent Decreases the indentation of the currently selected format block by one increment.
1781     \value AlignCenter Applies center alignment to content.
1782     \value AlignJustified Applies full justification to content.
1783     \value AlignLeft Applies left justification to content.
1784     \value AlignRight Applies right justification to content.
1785 
1786 
1787     \omitvalue WebActionCount
1788 
1789 */
1790 
1791 /*!
1792     \enum QWebPage::WebWindowType
1793 
1794     This enum describes the types of window that can be created by the createWindow() function.
1795 
1796     \value WebBrowserWindow The window is a regular web browser window.
1797     \value WebModalDialog The window acts as modal dialog.
1798 */
1799 
1800 
1801 /*!
1802     \class QWebPage::ViewportAttributes
1803     \since 4.7
1804     \brief The QWebPage::ViewportAttributes class describes hints that can be applied to a viewport.
1805 
1806     QWebPage::ViewportAttributes provides a description of a viewport, such as viewport geometry,
1807     initial scale factor with limits, plus information about whether a user should be able
1808     to scale the contents in the viewport or not, ie. by zooming.
1809 
1810     ViewportAttributes can be set by a web author using the viewport meta tag extension, documented
1811     at \l{http://developer.apple.com/safari/library/documentation/appleapplications/reference/safariwebcontent/usingtheviewport/usingtheviewport.html}{Safari Reference Library: Using the Viewport Meta Tag}.
1812 
1813     All values might not be set, as such when dealing with the hints, the developer needs to
1814     check whether the values are valid. Negative values denote an invalid qreal value.
1815 
1816     \inmodule QtWebKit
1817 */
1818 
1819 /*!
1820     Constructs an empty QWebPage::ViewportAttributes.
1821 */
ViewportAttributes()1822 QWebPage::ViewportAttributes::ViewportAttributes()
1823     : d(0)
1824     , m_initialScaleFactor(-1.0)
1825     , m_minimumScaleFactor(-1.0)
1826     , m_maximumScaleFactor(-1.0)
1827     , m_devicePixelRatio(-1.0)
1828     , m_isUserScalable(true)
1829     , m_isValid(false)
1830 {
1831 
1832 }
1833 
1834 /*!
1835     Constructs a QWebPage::ViewportAttributes which is a copy from \a other .
1836 */
ViewportAttributes(const QWebPage::ViewportAttributes & other)1837 QWebPage::ViewportAttributes::ViewportAttributes(const QWebPage::ViewportAttributes& other)
1838     : d(other.d)
1839     , m_initialScaleFactor(other.m_initialScaleFactor)
1840     , m_minimumScaleFactor(other.m_minimumScaleFactor)
1841     , m_maximumScaleFactor(other.m_maximumScaleFactor)
1842     , m_devicePixelRatio(other.m_devicePixelRatio)
1843     , m_isUserScalable(other.m_isUserScalable)
1844     , m_isValid(other.m_isValid)
1845     , m_size(other.m_size)
1846 {
1847 
1848 }
1849 
1850 /*!
1851     Destroys the QWebPage::ViewportAttributes.
1852 */
~ViewportAttributes()1853 QWebPage::ViewportAttributes::~ViewportAttributes()
1854 {
1855 
1856 }
1857 
1858 /*!
1859     Assigns the given QWebPage::ViewportAttributes to this viewport hints and returns a
1860     reference to this.
1861 */
operator =(const QWebPage::ViewportAttributes & other)1862 QWebPage::ViewportAttributes& QWebPage::ViewportAttributes::operator=(const QWebPage::ViewportAttributes& other)
1863 {
1864     if (this != &other) {
1865         d = other.d;
1866         m_initialScaleFactor = other.m_initialScaleFactor;
1867         m_minimumScaleFactor = other.m_minimumScaleFactor;
1868         m_maximumScaleFactor = other.m_maximumScaleFactor;
1869         m_isUserScalable = other.m_isUserScalable;
1870         m_isValid = other.m_isValid;
1871         m_size = other.m_size;
1872     }
1873 
1874     return *this;
1875 }
1876 
1877 /*! \fn inline bool QWebPage::ViewportAttributes::isValid() const
1878     Returns whether this is a valid ViewportAttributes or not.
1879 
1880     An invalid ViewportAttributes will have an empty QSize, negative values for scale factors and
1881     true for the boolean isUserScalable.
1882 */
1883 
1884 /*! \fn inline QSize QWebPage::ViewportAttributes::size() const
1885     Returns the size of the viewport.
1886 */
1887 
1888 /*! \fn inline qreal QWebPage::ViewportAttributes::initialScaleFactor() const
1889     Returns the initial scale of the viewport as a multiplier.
1890 */
1891 
1892 /*! \fn inline qreal QWebPage::ViewportAttributes::minimumScaleFactor() const
1893     Returns the minimum scale value of the viewport as a multiplier.
1894 */
1895 
1896 /*! \fn inline qreal QWebPage::ViewportAttributes::maximumScaleFactor() const
1897     Returns the maximum scale value of the viewport as a multiplier.
1898 */
1899 
1900 /*! \fn inline bool QWebPage::ViewportAttributes::isUserScalable() const
1901     Determines whether or not the scale can be modified by the user.
1902 */
1903 
1904 
1905 /*!
1906     \class QWebPage
1907     \since 4.4
1908     \brief The QWebPage class provides an object to view and edit web documents.
1909 
1910     \inmodule QtWebKit
1911 
1912     QWebPage holds a main frame responsible for web content, settings, the history
1913     of navigated links and actions. This class can be used, together with QWebFrame,
1914     to provide functionality like QWebView in a widget-less environment.
1915 
1916     QWebPage's API is very similar to QWebView, as you are still provided with
1917     common functions like action() (known as
1918     \l{QWebView::pageAction()}{pageAction}() in QWebView), triggerAction(),
1919     findText() and settings(). More QWebView-like functions can be found in the
1920     main frame of QWebPage, obtained via the mainFrame() function. For example,
1921     the \l{QWebFrame::load()}{load}(), \l{QWebFrame::setUrl()}{setUrl}() and
1922     \l{QWebFrame::setHtml()}{setHtml}() functions for QWebPage can be accessed
1923     using QWebFrame.
1924 
1925     The loadStarted() signal is emitted when the page begins to load.The
1926     loadProgress() signal, on the other hand, is emitted whenever an element
1927     of the web page completes loading, such as an embedded image, a script,
1928     etc. Finally, the loadFinished() signal is emitted when the page contents
1929     are loaded completely, independent of script execution or page rendering.
1930     Its argument, either true or false, indicates whether or not the load
1931     operation succeeded.
1932 
1933     \section1 Using QWebPage in a Widget-less Environment
1934 
1935     Before you begin painting a QWebPage object, you need to set the size of
1936     the viewport by calling setViewportSize(). Then, you invoke the main
1937     frame's render function (QWebFrame::render()). An example of this
1938     is shown in the code snippet below.
1939 
1940     Suppose we have a \c Thumbnail class as follows:
1941 
1942     \snippet webkitsnippets/webpage/main.cpp 0
1943 
1944     The \c Thumbnail's constructor takes in a \a url. We connect our QWebPage
1945     object's \l{QWebPage::}{loadFinished()} signal to our private slot,
1946     \c render().
1947 
1948     \snippet webkitsnippets/webpage/main.cpp 1
1949 
1950     The \c render() function shows how we can paint a thumbnail using a
1951     QWebPage object.
1952 
1953     \snippet webkitsnippets/webpage/main.cpp 2
1954 
1955     We begin by setting the \l{QWebPage::viewportSize()}{viewportSize} and
1956     then we instantiate a QImage object, \c image, with the same size as our
1957     \l{QWebPage::viewportSize()}{viewportSize}. This image is then sent
1958     as a parameter to \c painter. Next, we render the contents of the main
1959     frame and its subframes into \c painter. Finally, we save the scaled image.
1960 
1961     \sa QWebFrame
1962 */
1963 
1964 /*!
1965     Constructs an empty QWebPage with parent \a parent.
1966 */
QWebPage(QObject * parent)1967 QWebPage::QWebPage(QObject *parent)
1968     : QObject(parent)
1969     , d(new QWebPagePrivate(this))
1970 {
1971     setView(qobject_cast<QWidget*>(parent));
1972 
1973     connect(this, SIGNAL(loadProgress(int)), this, SLOT(_q_onLoadProgressChanged(int)));
1974 #ifndef NDEBUG
1975     connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(_q_cleanupLeakMessages()));
1976 #endif
1977 }
1978 
1979 /*!
1980     Destroys the web page.
1981 */
~QWebPage()1982 QWebPage::~QWebPage()
1983 {
1984     d->createMainFrame();
1985     FrameLoader *loader = d->mainFrame->d->frame->loader();
1986     if (loader)
1987         loader->detachFromParent();
1988     delete d;
1989 }
1990 
1991 /*!
1992     Returns the main frame of the page.
1993 
1994     The main frame provides access to the hierarchy of sub-frames and is also needed if you
1995     want to explicitly render a web page into a given painter.
1996 
1997     \sa currentFrame()
1998 */
mainFrame() const1999 QWebFrame *QWebPage::mainFrame() const
2000 {
2001     d->createMainFrame();
2002     return d->mainFrame;
2003 }
2004 
2005 /*!
2006     Returns the frame currently active.
2007 
2008     \sa mainFrame(), frameCreated()
2009 */
currentFrame() const2010 QWebFrame *QWebPage::currentFrame() const
2011 {
2012     d->createMainFrame();
2013     WebCore::Frame *frame = d->page->focusController()->focusedOrMainFrame();
2014     return qobject_cast<QWebFrame*>(frame->loader()->networkingContext()->originatingObject());
2015 }
2016 
2017 
2018 /*!
2019     \since 4.6
2020 
2021     Returns the frame at the given point \a pos, or 0 if there is no frame at
2022     that position.
2023 
2024     \sa mainFrame(), currentFrame()
2025 */
frameAt(const QPoint & pos) const2026 QWebFrame* QWebPage::frameAt(const QPoint& pos) const
2027 {
2028     QWebFrame* webFrame = mainFrame();
2029     if (!webFrame->geometry().contains(pos))
2030         return 0;
2031     QWebHitTestResult hitTestResult = webFrame->hitTestContent(pos);
2032     return hitTestResult.frame();
2033 }
2034 
2035 /*!
2036     Returns a pointer to the view's history of navigated web pages.
2037 */
history() const2038 QWebHistory *QWebPage::history() const
2039 {
2040     d->createMainFrame();
2041     return &d->history;
2042 }
2043 
2044 /*!
2045     Sets the \a view that is associated with the web page.
2046 
2047     \sa view()
2048 */
setView(QWidget * view)2049 void QWebPage::setView(QWidget* view)
2050 {
2051     if (this->view() == view)
2052         return;
2053 
2054     d->view = view;
2055     setViewportSize(view ? view->size() : QSize(0, 0));
2056 
2057     // If we have no client, we install a special client delegating
2058     // the responsibility to the QWidget. This is the code path
2059     // handling a.o. the "legacy" QWebView.
2060     //
2061     // If such a special delegate already exist, we substitute the view.
2062 
2063     if (d->client) {
2064         if (d->client->isQWidgetClient())
2065             static_cast<PageClientQWidget*>(d->client.get())->view = view;
2066         return;
2067     }
2068 
2069     if (view)
2070         d->client = adoptPtr(new PageClientQWidget(view, this));
2071 }
2072 
2073 /*!
2074     Returns the view widget that is associated with the web page.
2075 
2076     \sa setView()
2077 */
view() const2078 QWidget *QWebPage::view() const
2079 {
2080     return d->view.data();
2081 }
2082 
2083 /*!
2084     This function is called whenever a JavaScript program tries to print a \a message to the web browser's console.
2085 
2086     For example in case of evaluation errors the source URL may be provided in \a sourceID as well as the \a lineNumber.
2087 
2088     The default implementation prints nothing.
2089 */
javaScriptConsoleMessage(const QString & message,int lineNumber,const QString & sourceID)2090 void QWebPage::javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID)
2091 {
2092     Q_UNUSED(sourceID)
2093 
2094     // Catch plugin logDestroy message for LayoutTests/plugins/open-and-close-window-with-plugin.html
2095     // At this point DRT's WebPage has already been destroyed
2096     if (QWebPagePrivate::drtRun) {
2097         if (message == QLatin1String("PLUGIN: NPP_Destroy"))
2098             fprintf (stdout, "CONSOLE MESSAGE: line %d: %s\n", lineNumber, message.toUtf8().constData());
2099     }
2100 }
2101 
2102 /*!
2103     This function is called whenever a JavaScript program running inside \a frame calls the alert() function with
2104     the message \a msg.
2105 
2106     The default implementation shows the message, \a msg, with QMessageBox::information.
2107 */
javaScriptAlert(QWebFrame * frame,const QString & msg)2108 void QWebPage::javaScriptAlert(QWebFrame *frame, const QString& msg)
2109 {
2110     Q_UNUSED(frame)
2111 #ifndef QT_NO_MESSAGEBOX
2112     QWidget* parent = (d->client) ? d->client->ownerWidget() : 0;
2113     QMessageBox::information(parent, tr("JavaScript Alert - %1").arg(mainFrame()->url().host()), Qt::escape(msg), QMessageBox::Ok);
2114 #endif
2115 }
2116 
2117 /*!
2118     This function is called whenever a JavaScript program running inside \a frame calls the confirm() function
2119     with the message, \a msg. Returns true if the user confirms the message; otherwise returns false.
2120 
2121     The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons.
2122 */
javaScriptConfirm(QWebFrame * frame,const QString & msg)2123 bool QWebPage::javaScriptConfirm(QWebFrame *frame, const QString& msg)
2124 {
2125     Q_UNUSED(frame)
2126 #ifdef QT_NO_MESSAGEBOX
2127     return true;
2128 #else
2129     QWidget* parent = (d->client) ? d->client->ownerWidget() : 0;
2130     return QMessageBox::Yes == QMessageBox::information(parent, tr("JavaScript Confirm - %1").arg(mainFrame()->url().host()), Qt::escape(msg), QMessageBox::Yes, QMessageBox::No);
2131 #endif
2132 }
2133 
2134 /*!
2135     This function is called whenever a JavaScript program running inside \a frame tries to prompt the user for input.
2136     The program may provide an optional message, \a msg, as well as a default value for the input in \a defaultValue.
2137 
2138     If the prompt was cancelled by the user the implementation should return false; otherwise the
2139     result should be written to \a result and true should be returned. If the prompt was not cancelled by the
2140     user, the implementation should return true and the result string must not be null.
2141 
2142     The default implementation uses QInputDialog::getText().
2143 */
javaScriptPrompt(QWebFrame * frame,const QString & msg,const QString & defaultValue,QString * result)2144 bool QWebPage::javaScriptPrompt(QWebFrame *frame, const QString& msg, const QString& defaultValue, QString* result)
2145 {
2146     Q_UNUSED(frame)
2147     bool ok = false;
2148 #ifndef QT_NO_INPUTDIALOG
2149     QWidget* parent = (d->client) ? d->client->ownerWidget() : 0;
2150     QString x = QInputDialog::getText(parent, tr("JavaScript Prompt - %1").arg(mainFrame()->url().host()), Qt::escape(msg), QLineEdit::Normal, defaultValue, &ok);
2151     if (ok && result)
2152         *result = x;
2153 #endif
2154     return ok;
2155 }
2156 
2157 /*!
2158     \fn bool QWebPage::shouldInterruptJavaScript()
2159     \since 4.6
2160     This function is called when a JavaScript program is running for a long period of time.
2161 
2162     If the user wanted to stop the JavaScript the implementation should return true; otherwise false.
2163 
2164     The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons.
2165 
2166     \warning Because of binary compatibility constraints, this function is not virtual. If you want to
2167     provide your own implementation in a QWebPage subclass, reimplement the shouldInterruptJavaScript()
2168     slot in your subclass instead. QtWebKit will dynamically detect the slot and call it.
2169 */
shouldInterruptJavaScript()2170 bool QWebPage::shouldInterruptJavaScript()
2171 {
2172 #ifdef QT_NO_MESSAGEBOX
2173     return false;
2174 #else
2175     QWidget* parent = (d->client) ? d->client->ownerWidget() : 0;
2176     return QMessageBox::Yes == QMessageBox::information(parent, tr("JavaScript Problem - %1").arg(mainFrame()->url().host()), tr("The script on this page appears to have a problem. Do you want to stop the script?"), QMessageBox::Yes, QMessageBox::No);
2177 #endif
2178 }
2179 
setFeaturePermission(QWebFrame * frame,Feature feature,PermissionPolicy policy)2180 void QWebPage::setFeaturePermission(QWebFrame* frame, Feature feature, PermissionPolicy policy)
2181 {
2182     switch (feature) {
2183     case Notifications:
2184 #if ENABLE(NOTIFICATIONS)
2185         if (policy == PermissionGrantedByUser)
2186             NotificationPresenterClientQt::notificationPresenter()->allowNotificationForFrame(frame->d->frame);
2187 #endif
2188         break;
2189     case Geolocation:
2190 #if ENABLE(GEOLOCATION)
2191         GeolocationPermissionClientQt::geolocationPermissionClient()->setPermission(frame, policy);
2192 #endif
2193         break;
2194 
2195     default:
2196         break;
2197     }
2198 }
2199 
2200 /*!
2201     This function is called whenever WebKit wants to create a new window of the given \a type, for
2202     example when a JavaScript program requests to open a document in a new window.
2203 
2204     If the new window can be created, the new window's QWebPage is returned; otherwise a null pointer is returned.
2205 
2206     If the view associated with the web page is a QWebView object, then the default implementation forwards
2207     the request to QWebView's createWindow() function; otherwise it returns a null pointer.
2208 
2209     If \a type is WebModalDialog, the application must call setWindowModality(Qt::ApplicationModal) on the new window.
2210 
2211     \note In the cases when the window creation is being triggered by JavaScript, apart from
2212     reimplementing this method application must also set the JavaScriptCanOpenWindows attribute
2213     of QWebSettings to true in order for it to get called.
2214 
2215     \sa acceptNavigationRequest(), QWebView::createWindow()
2216 */
createWindow(WebWindowType type)2217 QWebPage *QWebPage::createWindow(WebWindowType type)
2218 {
2219     QWebView *webView = qobject_cast<QWebView*>(view());
2220     if (webView) {
2221         QWebView *newView = webView->createWindow(type);
2222         if (newView)
2223             return newView->page();
2224     }
2225     return 0;
2226 }
2227 
2228 /*!
2229     This function is called whenever WebKit encounters a HTML object element with type "application/x-qt-plugin". It is
2230     called regardless of the value of QWebSettings::PluginsEnabled. The \a classid, \a url, \a paramNames and \a paramValues
2231     correspond to the HTML object element attributes and child elements to configure the embeddable object.
2232 */
createPlugin(const QString & classid,const QUrl & url,const QStringList & paramNames,const QStringList & paramValues)2233 QObject *QWebPage::createPlugin(const QString &classid, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues)
2234 {
2235     Q_UNUSED(classid)
2236     Q_UNUSED(url)
2237     Q_UNUSED(paramNames)
2238     Q_UNUSED(paramValues)
2239     return 0;
2240 }
2241 
extractContentTypeFromHash(const HashSet<String> & types,QStringList * list)2242 static void extractContentTypeFromHash(const HashSet<String>& types, QStringList* list)
2243 {
2244     if (!list)
2245         return;
2246 
2247     HashSet<String>::const_iterator endIt = types.end();
2248     for (HashSet<String>::const_iterator it = types.begin(); it != endIt; ++it)
2249         *list << *it;
2250 }
2251 
extractContentTypeFromPluginVector(const Vector<PluginPackage * > & plugins,QStringList * list)2252 static void extractContentTypeFromPluginVector(const Vector<PluginPackage*>& plugins, QStringList* list)
2253 {
2254     if (!list)
2255         return;
2256 
2257     for (unsigned int i = 0; i < plugins.size(); ++i) {
2258         MIMEToDescriptionsMap::const_iterator map_it = plugins[i]->mimeToDescriptions().begin();
2259         MIMEToDescriptionsMap::const_iterator map_end = plugins[i]->mimeToDescriptions().end();
2260         for (; map_it != map_end; ++map_it)
2261             *list << map_it->first;
2262     }
2263 }
2264 
2265 /*!
2266  *  Returns the list of all content types supported by QWebPage.
2267  */
supportedContentTypes() const2268 QStringList QWebPage::supportedContentTypes() const
2269 {
2270     QStringList mimeTypes;
2271 
2272     extractContentTypeFromHash(MIMETypeRegistry::getSupportedImageMIMETypes(), &mimeTypes);
2273     extractContentTypeFromHash(MIMETypeRegistry::getSupportedNonImageMIMETypes(), &mimeTypes);
2274     if (d->page->settings() && d->page->settings()->arePluginsEnabled())
2275         extractContentTypeFromPluginVector(PluginDatabase::installedPlugins()->plugins(), &mimeTypes);
2276 
2277     return mimeTypes;
2278 }
2279 
2280 /*!
2281  *  Returns true if QWebPage can handle the given \a mimeType; otherwise, returns false.
2282  */
supportsContentType(const QString & mimeType) const2283 bool QWebPage::supportsContentType(const QString& mimeType) const
2284 {
2285     const String type = mimeType.toLower();
2286     if (MIMETypeRegistry::isSupportedImageMIMEType(type))
2287         return true;
2288 
2289     if (MIMETypeRegistry::isSupportedNonImageMIMEType(type))
2290         return true;
2291 
2292     if (d->page->settings() && d->page->settings()->arePluginsEnabled()
2293         && PluginDatabase::installedPlugins()->isMIMETypeRegistered(type))
2294         return true;
2295 
2296     return false;
2297 }
2298 
frameLoadRequest(const QUrl & url,WebCore::Frame * frame)2299 static WebCore::FrameLoadRequest frameLoadRequest(const QUrl &url, WebCore::Frame *frame)
2300 {
2301     return WebCore::FrameLoadRequest(frame->document()->securityOrigin(),
2302         WebCore::ResourceRequest(url, frame->loader()->outgoingReferrer()));
2303 }
2304 
openNewWindow(const QUrl & url,WebCore::Frame * frame)2305 static void openNewWindow(const QUrl& url, WebCore::Frame* frame)
2306 {
2307     if (Page* oldPage = frame->page()) {
2308         WindowFeatures features;
2309         NavigationAction action;
2310         FrameLoadRequest request = frameLoadRequest(url, frame);
2311         if (Page* newPage = oldPage->chrome()->createWindow(frame, request, features, action)) {
2312             newPage->mainFrame()->loader()->loadFrameRequest(request, false, false, 0, 0, SendReferrer);
2313             newPage->chrome()->show();
2314         }
2315     }
2316 }
2317 
collectChildFrames(QWebFrame * frame,QList<QWebFrame * > & list)2318 static void collectChildFrames(QWebFrame* frame, QList<QWebFrame*>& list)
2319 {
2320     list << frame->childFrames();
2321     QListIterator<QWebFrame*> it(frame->childFrames());
2322     while (it.hasNext()) {
2323         collectChildFrames(it.next(), list);
2324     }
2325 }
2326 
2327 /*!
2328     This function can be called to trigger the specified \a action.
2329     It is also called by QtWebKit if the user triggers the action, for example
2330     through a context menu item.
2331 
2332     If \a action is a checkable action then \a checked specified whether the action
2333     is toggled or not.
2334 
2335     \sa action()
2336 */
triggerAction(WebAction action,bool)2337 void QWebPage::triggerAction(WebAction action, bool)
2338 {
2339     WebCore::Frame *frame = d->page->focusController()->focusedOrMainFrame();
2340     if (!frame)
2341         return;
2342     WebCore::Editor *editor = frame->editor();
2343     const char *command = 0;
2344 
2345     switch (action) {
2346         case OpenLink:
2347             if (QWebFrame *targetFrame = d->hitTestResult.linkTargetFrame()) {
2348                 WTF::RefPtr<WebCore::Frame> wcFrame = targetFrame->d->frame;
2349                 targetFrame->d->frame->loader()->loadFrameRequest(frameLoadRequest(d->hitTestResult.linkUrl(), wcFrame.get()),
2350                                                                   /*lockHistory*/ false, /*lockBackForwardList*/ false, /*event*/ 0,
2351                                                                   /*FormState*/ 0, SendReferrer);
2352                 break;
2353             }
2354             // fall through
2355         case OpenLinkInNewWindow:
2356             openNewWindow(d->hitTestResult.linkUrl(), frame);
2357             break;
2358         case OpenFrameInNewWindow: {
2359             KURL url = frame->loader()->documentLoader()->unreachableURL();
2360             if (url.isEmpty())
2361                 url = frame->loader()->documentLoader()->url();
2362             openNewWindow(url, frame);
2363             break;
2364         }
2365         case CopyLinkToClipboard: {
2366 #if defined(Q_WS_X11)
2367             bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode();
2368             Pasteboard::generalPasteboard()->setSelectionMode(true);
2369             editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText());
2370             Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode);
2371 #endif
2372             editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText());
2373             break;
2374         }
2375         case OpenImageInNewWindow:
2376             openNewWindow(d->hitTestResult.imageUrl(), frame);
2377             break;
2378         case DownloadImageToDisk:
2379             frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.imageUrl(), frame->loader()->outgoingReferrer()));
2380             break;
2381         case DownloadLinkToDisk:
2382             frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.linkUrl(), frame->loader()->outgoingReferrer()));
2383             break;
2384 #ifndef QT_NO_CLIPBOARD
2385         case CopyImageToClipboard:
2386             QApplication::clipboard()->setPixmap(d->hitTestResult.pixmap());
2387             break;
2388         case CopyImageUrlToClipboard:
2389             QApplication::clipboard()->setText(d->hitTestResult.imageUrl().toString());
2390             break;
2391 #endif
2392         case Back:
2393             d->page->goBack();
2394             break;
2395         case Forward:
2396             d->page->goForward();
2397             break;
2398         case Stop:
2399             mainFrame()->d->frame->loader()->stopForUserCancel();
2400             d->updateNavigationActions();
2401             break;
2402         case Reload:
2403             mainFrame()->d->frame->loader()->reload(/*endtoendreload*/false);
2404             break;
2405         case ReloadAndBypassCache:
2406             mainFrame()->d->frame->loader()->reload(/*endtoendreload*/true);
2407             break;
2408         case SetTextDirectionDefault:
2409             editor->setBaseWritingDirection(NaturalWritingDirection);
2410             break;
2411         case SetTextDirectionLeftToRight:
2412             editor->setBaseWritingDirection(LeftToRightWritingDirection);
2413             break;
2414         case SetTextDirectionRightToLeft:
2415             editor->setBaseWritingDirection(RightToLeftWritingDirection);
2416             break;
2417         case InspectElement: {
2418 #if ENABLE(INSPECTOR)
2419             if (!d->hitTestResult.isNull()) {
2420                 d->getOrCreateInspector(); // Make sure the inspector is created
2421                 d->inspector->show(); // The inspector is expected to be shown on inspection
2422                 d->page->inspectorController()->inspect(d->hitTestResult.d->innerNonSharedNode.get());
2423             }
2424 #endif
2425             break;
2426         }
2427         case StopScheduledPageRefresh: {
2428             QWebFrame* topFrame = mainFrame();
2429             topFrame->d->frame->navigationScheduler()->cancel();
2430             QList<QWebFrame*> childFrames;
2431             collectChildFrames(topFrame, childFrames);
2432             QListIterator<QWebFrame*> it(childFrames);
2433             while (it.hasNext())
2434                 it.next()->d->frame->navigationScheduler()->cancel();
2435             break;
2436         }
2437         default:
2438             command = QWebPagePrivate::editorCommandForWebActions(action);
2439             break;
2440     }
2441 
2442     if (command)
2443         editor->command(command).execute();
2444 }
2445 
viewportSize() const2446 QSize QWebPage::viewportSize() const
2447 {
2448     if (d->mainFrame && d->mainFrame->d->frame->view())
2449         return d->mainFrame->d->frame->view()->frameRect().size();
2450 
2451     return d->viewportSize;
2452 }
2453 
2454 /*!
2455     \property QWebPage::viewportSize
2456     \brief the size of the viewport
2457 
2458     The size affects for example the visibility of scrollbars
2459     if the document is larger than the viewport.
2460 
2461     By default, for a newly-created Web page, this property contains a size with
2462     zero width and height.
2463 
2464     \sa QWebFrame::render(), preferredContentsSize
2465 */
setViewportSize(const QSize & size) const2466 void QWebPage::setViewportSize(const QSize &size) const
2467 {
2468     d->viewportSize = size;
2469 
2470     QWebFrame *frame = mainFrame();
2471     if (frame->d->frame && frame->d->frame->view()) {
2472         WebCore::FrameView* view = frame->d->frame->view();
2473         view->resize(size);
2474         view->adjustViewSize();
2475     }
2476 }
2477 
getintenv(const char * variable)2478 static int getintenv(const char* variable)
2479 {
2480     bool ok;
2481     int value = qgetenv(variable).toInt(&ok);
2482     return (ok) ? value : -1;
2483 }
2484 
queryDeviceSizeForScreenContainingWidget(const QWidget * widget)2485 static QSize queryDeviceSizeForScreenContainingWidget(const QWidget* widget)
2486 {
2487     QDesktopWidget* desktop = QApplication::desktop();
2488     if (!desktop)
2489         return QSize();
2490 
2491     QSize size;
2492 
2493     if (widget) {
2494         // Returns the available geometry of the screen which contains widget.
2495         // NOTE: this must be the the full screen size including any fixed status areas etc.
2496         size = desktop->availableGeometry(widget).size();
2497     } else
2498         size = desktop->availableGeometry().size();
2499 
2500     // This must be in portrait mode, adjust if not.
2501     if (size.width() > size.height()) {
2502         int width = size.width();
2503         size.setWidth(size.height());
2504         size.setHeight(width);
2505     }
2506 
2507     return size;
2508 }
2509 
2510 /*!
2511     Computes the optimal viewport configuration given the \a availableSize, when
2512     user interface components are disregarded.
2513 
2514     The configuration is also dependent on the device screen size which is obtained
2515     automatically. For testing purposes the size can be overridden by setting two
2516     environment variables QTWEBKIT_DEVICE_WIDTH and QTWEBKIT_DEVICE_HEIGHT, which
2517     both needs to be set.
2518 
2519     The ViewportAttributes includes a pixel density ratio, which will also be exposed to
2520     the web author though the -webkit-pixel-ratio media feature. This is the ratio
2521     between 1 density-independent pixel (DPI) and physical pixels.
2522 
2523     A density-independent pixel is equivalent to one physical pixel on a 160 DPI screen,
2524     so on our platform assumes that as the baseline density.
2525 
2526     The conversion of DIP units to screen pixels is quite simple:
2527 
2528     pixels = DIPs * (density / 160).
2529 
2530     Thus, on a 240 DPI screen, 1 DIPs would equal 1.5 physical pixels.
2531 
2532     An invalid instance will be returned in the case an empty size is passed to the
2533     method.
2534 
2535     \note The density is automatically obtained from the DPI of the screen where the page
2536     is being shown, but as many X11 servers are reporting wrong DPI, it is possible to
2537     override it using QX11Info::setAppDpiY().
2538 */
2539 
viewportAttributesForSize(const QSize & availableSize) const2540 QWebPage::ViewportAttributes QWebPage::viewportAttributesForSize(const QSize& availableSize) const
2541 {
2542     static int desktopWidth = 980;
2543 
2544     ViewportAttributes result;
2545 
2546      if (availableSize.isEmpty())
2547          return result; // Returns an invalid instance.
2548 
2549     int deviceWidth = getintenv("QTWEBKIT_DEVICE_WIDTH");
2550     int deviceHeight = getintenv("QTWEBKIT_DEVICE_HEIGHT");
2551 
2552     // Both environment variables need to be set - or they will be ignored.
2553     if (deviceWidth < 0 && deviceHeight < 0) {
2554         QSize size = queryDeviceSizeForScreenContainingWidget((d->client) ? d->client->ownerWidget() : 0);
2555         deviceWidth = size.width();
2556         deviceHeight = size.height();
2557     }
2558 
2559     WebCore::ViewportAttributes conf = WebCore::computeViewportAttributes(d->viewportArguments(), desktopWidth, deviceWidth, deviceHeight, qt_defaultDpi(), availableSize);
2560 
2561     result.m_isValid = true;
2562     result.m_size = conf.layoutSize;
2563     result.m_initialScaleFactor = conf.initialScale;
2564     result.m_minimumScaleFactor = conf.minimumScale;
2565     result.m_maximumScaleFactor = conf.maximumScale;
2566     result.m_devicePixelRatio = conf.devicePixelRatio;
2567     result.m_isUserScalable = static_cast<bool>(conf.userScalable);
2568 
2569     d->pixelRatio = conf.devicePixelRatio;
2570 
2571     return result;
2572 }
2573 
preferredContentsSize() const2574 QSize QWebPage::preferredContentsSize() const
2575 {
2576     QWebFrame* frame = d->mainFrame;
2577     if (frame) {
2578         WebCore::FrameView* view = frame->d->frame->view();
2579         if (view && view->useFixedLayout())
2580             return d->mainFrame->d->frame->view()->fixedLayoutSize();
2581     }
2582 
2583     return d->fixedLayoutSize;
2584 }
2585 
2586 /*!
2587     \property QWebPage::preferredContentsSize
2588     \since 4.6
2589     \brief a custom size used for laying out the page contents.
2590 
2591     By default all pages are laid out using the viewport of the page as the base.
2592 
2593     As pages mostly are designed for desktop usage, they often do not layout properly
2594     on small devices as the contents require a certain view width. For this reason
2595     it is common to use a different layout size and then scale the contents to fit
2596     within the actual view.
2597 
2598     If this property is set to a valid size, this size is used for all layout needs
2599     instead of the size of the viewport.
2600 
2601     Setting an invalid size, makes the page fall back to using the viewport size for layout.
2602 
2603     \sa viewportSize
2604 */
setPreferredContentsSize(const QSize & size) const2605 void QWebPage::setPreferredContentsSize(const QSize& size) const
2606 {
2607     // FIXME: Rename this method to setCustomLayoutSize
2608 
2609     d->fixedLayoutSize = size;
2610 
2611     QWebFrame* frame = mainFrame();
2612     if (!frame->d->frame || !frame->d->frame->view())
2613         return;
2614 
2615     WebCore::FrameView* view = frame->d->frame->view();
2616 
2617     if (size.isValid()) {
2618         view->setUseFixedLayout(true);
2619         view->setFixedLayoutSize(size);
2620     } else if (view->useFixedLayout())
2621         view->setUseFixedLayout(false);
2622 
2623     view->layout();
2624 }
2625 
2626 /*
2627     This function is to be called after any (animated) scroll/pan has ended, in the case the application handles the
2628     scrolling/panning of the web contents. This is commonly used in combination with tiling where is it common for
2629     the application to pan the actual view, which then resizes itself to the size of the contents.
2630 
2631     \note Calling this function makes WebKit stop trying to calculate the visibleContentRect. To turn that on
2632     again, call this method with an empty rect.
2633 
2634     \sa QGraphicsWebView::resizesToContents, QWebSettings::TiledBackingStoreEnabled
2635 */
setActualVisibleContentRect(const QRect & rect) const2636 void QWebPage::setActualVisibleContentRect(const QRect& rect) const
2637 {
2638     QWebFrame* frame = mainFrame();
2639     if (!frame->d->frame || !frame->d->frame->view())
2640         return;
2641 
2642     WebCore::FrameView* view = frame->d->frame->view();
2643     view->setActualVisibleContentRect(rect);
2644 }
2645 
2646 /*!
2647     \fn bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
2648 
2649     This function is called whenever WebKit requests to navigate \a frame to the resource specified by \a request by means of
2650     the specified navigation type \a type.
2651 
2652     If \a frame is a null pointer then navigation to a new window is requested. If the request is
2653     accepted createWindow() will be called.
2654 
2655     The default implementation interprets the page's linkDelegationPolicy and emits linkClicked accordingly or returns true
2656     to let QWebPage handle the navigation itself.
2657 
2658     \sa createWindow()
2659 */
acceptNavigationRequest(QWebFrame * frame,const QNetworkRequest & request,QWebPage::NavigationType type)2660 bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
2661 {
2662     Q_UNUSED(frame)
2663     if (type == NavigationTypeLinkClicked) {
2664         switch (d->linkPolicy) {
2665             case DontDelegateLinks:
2666                 return true;
2667 
2668             case DelegateExternalLinks:
2669                 if (WebCore::SchemeRegistry::shouldTreatURLSchemeAsLocal(request.url().scheme()))
2670                     return true;
2671                 emit linkClicked(request.url());
2672                 return false;
2673 
2674             case DelegateAllLinks:
2675                 emit linkClicked(request.url());
2676                 return false;
2677         }
2678     }
2679     return true;
2680 }
2681 
2682 /*!
2683     \property QWebPage::hasSelection
2684     \brief whether this page contains selected content or not.
2685 
2686     \sa selectionChanged()
2687 */
hasSelection() const2688 bool QWebPage::hasSelection() const
2689 {
2690     d->createMainFrame();
2691     WebCore::Frame* frame = d->page->focusController()->focusedOrMainFrame();
2692     if (frame)
2693         return (frame->selection()->selection().selectionType() != VisibleSelection::NoSelection);
2694     return false;
2695 }
2696 
2697 /*!
2698     \property QWebPage::selectedText
2699     \brief the text currently selected
2700 
2701     By default, this property contains an empty string.
2702 
2703     \sa selectionChanged(), selectedHtml()
2704 */
selectedText() const2705 QString QWebPage::selectedText() const
2706 {
2707     d->createMainFrame();
2708     WebCore::Frame* frame = d->page->focusController()->focusedOrMainFrame();
2709     if (frame->selection()->selection().selectionType() == VisibleSelection::NoSelection)
2710         return QString();
2711     return frame->editor()->selectedText();
2712 }
2713 
2714 /*!
2715     \since 4.8
2716     \property QWebPage::selectedHtml
2717     \brief the HTML currently selected
2718 
2719     By default, this property contains an empty string.
2720 
2721     \sa selectionChanged(), selectedText()
2722 */
selectedHtml() const2723 QString QWebPage::selectedHtml() const
2724 {
2725     d->createMainFrame();
2726     return d->page->focusController()->focusedOrMainFrame()->editor()->selectedRange()->toHTML();
2727 }
2728 
2729 #ifndef QT_NO_ACTION
2730 /*!
2731    Returns a QAction for the specified WebAction \a action.
2732 
2733    The action is owned by the QWebPage but you can customize the look by
2734    changing its properties.
2735 
2736    QWebPage also takes care of implementing the action, so that upon
2737    triggering the corresponding action is performed on the page.
2738 
2739    \sa triggerAction()
2740 */
action(WebAction action) const2741 QAction *QWebPage::action(WebAction action) const
2742 {
2743     if (action == QWebPage::NoWebAction) return 0;
2744     if (d->actions[action])
2745         return d->actions[action];
2746 
2747     QString text;
2748     QIcon icon;
2749     QStyle *style = d->client ? d->client->style() : qApp->style();
2750     bool checkable = false;
2751 
2752     switch (action) {
2753         case OpenLink:
2754             text = contextMenuItemTagOpenLink();
2755             break;
2756         case OpenLinkInNewWindow:
2757             text = contextMenuItemTagOpenLinkInNewWindow();
2758             break;
2759         case OpenFrameInNewWindow:
2760             text = contextMenuItemTagOpenFrameInNewWindow();
2761             break;
2762 
2763         case DownloadLinkToDisk:
2764             text = contextMenuItemTagDownloadLinkToDisk();
2765             break;
2766         case CopyLinkToClipboard:
2767             text = contextMenuItemTagCopyLinkToClipboard();
2768             break;
2769 
2770         case OpenImageInNewWindow:
2771             text = contextMenuItemTagOpenImageInNewWindow();
2772             break;
2773         case DownloadImageToDisk:
2774             text = contextMenuItemTagDownloadImageToDisk();
2775             break;
2776         case CopyImageToClipboard:
2777             text = contextMenuItemTagCopyImageToClipboard();
2778             break;
2779         case CopyImageUrlToClipboard:
2780             text = contextMenuItemTagCopyImageUrlToClipboard();
2781             break;
2782 
2783         case Back:
2784             text = contextMenuItemTagGoBack();
2785             icon = style->standardIcon(QStyle::SP_ArrowBack);
2786             break;
2787         case Forward:
2788             text = contextMenuItemTagGoForward();
2789             icon = style->standardIcon(QStyle::SP_ArrowForward);
2790             break;
2791         case Stop:
2792             text = contextMenuItemTagStop();
2793             icon = style->standardIcon(QStyle::SP_BrowserStop);
2794             break;
2795         case Reload:
2796             text = contextMenuItemTagReload();
2797             icon = style->standardIcon(QStyle::SP_BrowserReload);
2798             break;
2799 
2800         case Cut:
2801             text = contextMenuItemTagCut();
2802             break;
2803         case Copy:
2804             text = contextMenuItemTagCopy();
2805             break;
2806         case Paste:
2807             text = contextMenuItemTagPaste();
2808             break;
2809         case SelectAll:
2810             text = contextMenuItemTagSelectAll();
2811             break;
2812 #ifndef QT_NO_UNDOSTACK
2813         case Undo: {
2814             QAction *a = undoStack()->createUndoAction(d->q);
2815             d->actions[action] = a;
2816             return a;
2817         }
2818         case Redo: {
2819             QAction *a = undoStack()->createRedoAction(d->q);
2820             d->actions[action] = a;
2821             return a;
2822         }
2823 #endif // QT_NO_UNDOSTACK
2824         case MoveToNextChar:
2825             text = tr("Move the cursor to the next character");
2826             break;
2827         case MoveToPreviousChar:
2828             text = tr("Move the cursor to the previous character");
2829             break;
2830         case MoveToNextWord:
2831             text = tr("Move the cursor to the next word");
2832             break;
2833         case MoveToPreviousWord:
2834             text = tr("Move the cursor to the previous word");
2835             break;
2836         case MoveToNextLine:
2837             text = tr("Move the cursor to the next line");
2838             break;
2839         case MoveToPreviousLine:
2840             text = tr("Move the cursor to the previous line");
2841             break;
2842         case MoveToStartOfLine:
2843             text = tr("Move the cursor to the start of the line");
2844             break;
2845         case MoveToEndOfLine:
2846             text = tr("Move the cursor to the end of the line");
2847             break;
2848         case MoveToStartOfBlock:
2849             text = tr("Move the cursor to the start of the block");
2850             break;
2851         case MoveToEndOfBlock:
2852             text = tr("Move the cursor to the end of the block");
2853             break;
2854         case MoveToStartOfDocument:
2855             text = tr("Move the cursor to the start of the document");
2856             break;
2857         case MoveToEndOfDocument:
2858             text = tr("Move the cursor to the end of the document");
2859             break;
2860         case SelectNextChar:
2861             text = tr("Select to the next character");
2862             break;
2863         case SelectPreviousChar:
2864             text = tr("Select to the previous character");
2865             break;
2866         case SelectNextWord:
2867             text = tr("Select to the next word");
2868             break;
2869         case SelectPreviousWord:
2870             text = tr("Select to the previous word");
2871             break;
2872         case SelectNextLine:
2873             text = tr("Select to the next line");
2874             break;
2875         case SelectPreviousLine:
2876             text = tr("Select to the previous line");
2877             break;
2878         case SelectStartOfLine:
2879             text = tr("Select to the start of the line");
2880             break;
2881         case SelectEndOfLine:
2882             text = tr("Select to the end of the line");
2883             break;
2884         case SelectStartOfBlock:
2885             text = tr("Select to the start of the block");
2886             break;
2887         case SelectEndOfBlock:
2888             text = tr("Select to the end of the block");
2889             break;
2890         case SelectStartOfDocument:
2891             text = tr("Select to the start of the document");
2892             break;
2893         case SelectEndOfDocument:
2894             text = tr("Select to the end of the document");
2895             break;
2896         case DeleteStartOfWord:
2897             text = tr("Delete to the start of the word");
2898             break;
2899         case DeleteEndOfWord:
2900             text = tr("Delete to the end of the word");
2901             break;
2902 
2903         case SetTextDirectionDefault:
2904             text = contextMenuItemTagDefaultDirection();
2905             break;
2906         case SetTextDirectionLeftToRight:
2907             text = contextMenuItemTagLeftToRight();
2908             checkable = true;
2909             break;
2910         case SetTextDirectionRightToLeft:
2911             text = contextMenuItemTagRightToLeft();
2912             checkable = true;
2913             break;
2914 
2915         case ToggleBold:
2916             text = contextMenuItemTagBold();
2917             checkable = true;
2918             break;
2919         case ToggleItalic:
2920             text = contextMenuItemTagItalic();
2921             checkable = true;
2922             break;
2923         case ToggleUnderline:
2924             text = contextMenuItemTagUnderline();
2925             checkable = true;
2926             break;
2927 
2928         case InspectElement:
2929             text = contextMenuItemTagInspectElement();
2930             break;
2931 
2932         case InsertParagraphSeparator:
2933             text = tr("Insert a new paragraph");
2934             break;
2935         case InsertLineSeparator:
2936             text = tr("Insert a new line");
2937             break;
2938 
2939         case PasteAndMatchStyle:
2940             text = tr("Paste and Match Style");
2941             break;
2942         case RemoveFormat:
2943             text = tr("Remove formatting");
2944             break;
2945 
2946         case ToggleStrikethrough:
2947             text = tr("Strikethrough");
2948             checkable = true;
2949             break;
2950         case ToggleSubscript:
2951             text = tr("Subscript");
2952             checkable = true;
2953             break;
2954         case ToggleSuperscript:
2955             text = tr("Superscript");
2956             checkable = true;
2957             break;
2958         case InsertUnorderedList:
2959             text = tr("Insert Bulleted List");
2960             checkable = true;
2961             break;
2962         case InsertOrderedList:
2963             text = tr("Insert Numbered List");
2964             checkable = true;
2965             break;
2966         case Indent:
2967             text = tr("Indent");
2968             break;
2969         case Outdent:
2970             text = tr("Outdent");
2971             break;
2972         case AlignCenter:
2973             text = tr("Center");
2974             break;
2975         case AlignJustified:
2976             text = tr("Justify");
2977             break;
2978         case AlignLeft:
2979             text = tr("Align Left");
2980             break;
2981         case AlignRight:
2982             text = tr("Align Right");
2983             break;
2984         case NoWebAction:
2985             return 0;
2986         default:
2987             break;
2988     }
2989 
2990     if (text.isEmpty())
2991         return 0;
2992 
2993     QAction *a = new QAction(d->q);
2994     a->setText(text);
2995     a->setData(action);
2996     a->setCheckable(checkable);
2997     a->setIcon(icon);
2998 
2999     connect(a, SIGNAL(triggered(bool)),
3000             this, SLOT(_q_webActionTriggered(bool)));
3001 
3002     d->actions[action] = a;
3003     d->updateAction(action);
3004     return a;
3005 }
3006 #endif // QT_NO_ACTION
3007 
3008 /*!
3009     \property QWebPage::modified
3010     \brief whether the page contains unsubmitted form data, or the contents have been changed.
3011 
3012     By default, this property is false.
3013 
3014     \sa contentsChanged(), contentEditable, undoStack()
3015 */
isModified() const3016 bool QWebPage::isModified() const
3017 {
3018 #ifdef QT_NO_UNDOSTACK
3019     return false;
3020 #else
3021     if (!d->undoStack)
3022         return false;
3023     return d->undoStack->canUndo();
3024 #endif // QT_NO_UNDOSTACK
3025 }
3026 
3027 #ifndef QT_NO_UNDOSTACK
3028 /*!
3029     Returns a pointer to the undo stack used for editable content.
3030 
3031     \sa modified
3032 */
undoStack() const3033 QUndoStack *QWebPage::undoStack() const
3034 {
3035     if (!d->undoStack)
3036         d->undoStack = new QUndoStack(const_cast<QWebPage *>(this));
3037 
3038     return d->undoStack;
3039 }
3040 #endif // QT_NO_UNDOSTACK
3041 
3042 /*! \reimp
3043 */
event(QEvent * ev)3044 bool QWebPage::event(QEvent *ev)
3045 {
3046     switch (ev->type()) {
3047     case QEvent::Timer:
3048         d->timerEvent(static_cast<QTimerEvent*>(ev));
3049         break;
3050     case QEvent::MouseMove:
3051         d->mouseMoveEvent(static_cast<QMouseEvent*>(ev));
3052         break;
3053     case QEvent::MouseButtonPress:
3054         d->mousePressEvent(static_cast<QMouseEvent*>(ev));
3055         break;
3056     case QEvent::MouseButtonDblClick:
3057         d->mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev));
3058         break;
3059     case QEvent::MouseButtonRelease:
3060         d->mouseReleaseEvent(static_cast<QMouseEvent*>(ev));
3061         break;
3062 #if !defined(QT_NO_GRAPHICSVIEW)
3063     case QEvent::GraphicsSceneMouseMove:
3064         d->mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent*>(ev));
3065         break;
3066     case QEvent::GraphicsSceneMousePress:
3067         d->mousePressEvent(static_cast<QGraphicsSceneMouseEvent*>(ev));
3068         break;
3069     case QEvent::GraphicsSceneMouseDoubleClick:
3070         d->mouseDoubleClickEvent(static_cast<QGraphicsSceneMouseEvent*>(ev));
3071         break;
3072     case QEvent::GraphicsSceneMouseRelease:
3073         d->mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent*>(ev));
3074         break;
3075 #endif
3076 #ifndef QT_NO_CONTEXTMENU
3077     case QEvent::ContextMenu:
3078         d->contextMenuEvent(static_cast<QContextMenuEvent*>(ev)->globalPos());
3079         break;
3080 #if !defined(QT_NO_GRAPHICSVIEW)
3081     case QEvent::GraphicsSceneContextMenu:
3082         d->contextMenuEvent(static_cast<QGraphicsSceneContextMenuEvent*>(ev)->screenPos());
3083         break;
3084 #endif
3085 #endif
3086 #ifndef QT_NO_WHEELEVENT
3087     case QEvent::Wheel:
3088         d->wheelEvent(static_cast<QWheelEvent*>(ev));
3089         break;
3090 #if !defined(QT_NO_GRAPHICSVIEW)
3091     case QEvent::GraphicsSceneWheel:
3092         d->wheelEvent(static_cast<QGraphicsSceneWheelEvent*>(ev));
3093         break;
3094 #endif
3095 #endif
3096     case QEvent::KeyPress:
3097         d->keyPressEvent(static_cast<QKeyEvent*>(ev));
3098         break;
3099     case QEvent::KeyRelease:
3100         d->keyReleaseEvent(static_cast<QKeyEvent*>(ev));
3101         break;
3102     case QEvent::FocusIn:
3103         d->focusInEvent(static_cast<QFocusEvent*>(ev));
3104         break;
3105     case QEvent::FocusOut:
3106         d->focusOutEvent(static_cast<QFocusEvent*>(ev));
3107         break;
3108 #ifndef QT_NO_DRAGANDDROP
3109     case QEvent::DragEnter:
3110         d->dragEnterEvent(static_cast<QDragEnterEvent*>(ev));
3111         break;
3112     case QEvent::DragLeave:
3113         d->dragLeaveEvent(static_cast<QDragLeaveEvent*>(ev));
3114         break;
3115     case QEvent::DragMove:
3116         d->dragMoveEvent(static_cast<QDragMoveEvent*>(ev));
3117         break;
3118     case QEvent::Drop:
3119         d->dropEvent(static_cast<QDropEvent*>(ev));
3120         break;
3121 #if !defined(QT_NO_GRAPHICSVIEW)
3122     case QEvent::GraphicsSceneDragEnter:
3123         d->dragEnterEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
3124         break;
3125     case QEvent::GraphicsSceneDragMove:
3126         d->dragMoveEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
3127         break;
3128     case QEvent::GraphicsSceneDragLeave:
3129         d->dragLeaveEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
3130         break;
3131     case QEvent::GraphicsSceneDrop:
3132         d->dropEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
3133         break;
3134 #endif
3135 
3136 #endif
3137     case QEvent::InputMethod:
3138         d->inputMethodEvent(static_cast<QInputMethodEvent*>(ev));
3139         break;
3140     case QEvent::ShortcutOverride:
3141         d->shortcutOverrideEvent(static_cast<QKeyEvent*>(ev));
3142         break;
3143     case QEvent::Leave:
3144         d->leaveEvent(ev);
3145         break;
3146     case QEvent::TouchBegin:
3147     case QEvent::TouchUpdate:
3148     case QEvent::TouchEnd:
3149         // Return whether the default action was cancelled in the JS event handler
3150         return d->touchEvent(static_cast<QTouchEvent*>(ev));
3151 #ifndef QT_NO_PROPERTIES
3152     case QEvent::DynamicPropertyChange:
3153         d->dynamicPropertyChangeEvent(static_cast<QDynamicPropertyChangeEvent*>(ev));
3154         break;
3155 #endif
3156     default:
3157         return QObject::event(ev);
3158     }
3159 
3160     return true;
3161 }
3162 
3163 /*!
3164     Similar to QWidget::focusNextPrevChild() it focuses the next focusable web element
3165     if \a next is true; otherwise the previous element is focused.
3166 
3167     Returns true if it can find a new focusable element, or false if it can't.
3168 */
focusNextPrevChild(bool next)3169 bool QWebPage::focusNextPrevChild(bool next)
3170 {
3171     QKeyEvent ev(QEvent::KeyPress, Qt::Key_Tab, Qt::KeyboardModifiers(next ? Qt::NoModifier : Qt::ShiftModifier));
3172     d->keyPressEvent(&ev);
3173     bool hasFocusedNode = false;
3174     Frame *frame = d->page->focusController()->focusedFrame();
3175     if (frame) {
3176         Document *document = frame->document();
3177         hasFocusedNode = document && document->focusedNode();
3178     }
3179     //qDebug() << "focusNextPrevChild(" << next << ") =" << ev.isAccepted() << "focusedNode?" << hasFocusedNode;
3180     return hasFocusedNode;
3181 }
3182 
3183 /*!
3184     \property QWebPage::contentEditable
3185     \brief whether the content in this QWebPage is editable or not
3186     \since 4.5
3187 
3188     If this property is enabled the contents of the page can be edited by the user through a visible
3189     cursor. If disabled (the default) only HTML elements in the web page with their
3190     \c{contenteditable} attribute set are editable.
3191 
3192     \sa modified, contentsChanged(), WebAction
3193 */
setContentEditable(bool editable)3194 void QWebPage::setContentEditable(bool editable)
3195 {
3196     if (isContentEditable() != editable) {
3197         d->page->setEditable(editable);
3198         d->page->setTabKeyCyclesThroughElements(!editable);
3199         if (d->mainFrame) {
3200             WebCore::Frame* frame = d->mainFrame->d->frame;
3201             if (editable) {
3202                 frame->editor()->applyEditingStyleToBodyElement();
3203                 // FIXME: mac port calls this if there is no selectedDOMRange
3204                 //frame->setSelectionFromNone();
3205             }
3206         }
3207 
3208         d->updateEditorActions();
3209     }
3210 }
3211 
isContentEditable() const3212 bool QWebPage::isContentEditable() const
3213 {
3214     return d->page->isEditable();
3215 }
3216 
setDevicePixelRatio(qreal devicePixelRatio)3217 void QWebPage::setDevicePixelRatio(qreal devicePixelRatio)
3218 {
3219     d->pixelRatio = devicePixelRatio;
3220 }
3221 
3222 /*!
3223     \property QWebPage::forwardUnsupportedContent
3224     \brief whether QWebPage should forward unsupported content
3225 
3226     If enabled, the unsupportedContent() signal is emitted with a network reply that
3227     can be used to read the content.
3228 
3229     If disabled, the download of such content is aborted immediately.
3230 
3231     By default unsupported content is not forwarded.
3232 */
3233 
setForwardUnsupportedContent(bool forward)3234 void QWebPage::setForwardUnsupportedContent(bool forward)
3235 {
3236     d->forwardUnsupportedContent = forward;
3237 }
3238 
forwardUnsupportedContent() const3239 bool QWebPage::forwardUnsupportedContent() const
3240 {
3241     return d->forwardUnsupportedContent;
3242 }
3243 
3244 /*!
3245     \property QWebPage::linkDelegationPolicy
3246     \brief how QWebPage should delegate the handling of links through the
3247     linkClicked() signal
3248 
3249     The default is to delegate no links.
3250 */
3251 
setLinkDelegationPolicy(LinkDelegationPolicy policy)3252 void QWebPage::setLinkDelegationPolicy(LinkDelegationPolicy policy)
3253 {
3254     d->linkPolicy = policy;
3255 }
3256 
linkDelegationPolicy() const3257 QWebPage::LinkDelegationPolicy QWebPage::linkDelegationPolicy() const
3258 {
3259     return d->linkPolicy;
3260 }
3261 
3262 #ifndef QT_NO_CONTEXTMENU
3263 /*!
3264     Filters the context menu event, \a event, through handlers for scrollbars and
3265     custom event handlers in the web page. Returns true if the event was handled;
3266     otherwise false.
3267 
3268     A web page may swallow a context menu event through a custom event handler, allowing for context
3269     menus to be implemented in HTML/JavaScript. This is used by \l{http://maps.google.com/}{Google
3270     Maps}, for example.
3271 */
swallowContextMenuEvent(QContextMenuEvent * event)3272 bool QWebPage::swallowContextMenuEvent(QContextMenuEvent *event)
3273 {
3274     d->page->contextMenuController()->clearContextMenu();
3275 
3276     if (QWebFrame* webFrame = frameAt(event->pos())) {
3277         Frame* frame = QWebFramePrivate::core(webFrame);
3278         if (Scrollbar* scrollbar = frame->view()->scrollbarAtPoint(PlatformMouseEvent(event, 1).pos()))
3279             return scrollbar->contextMenu(PlatformMouseEvent(event, 1));
3280     }
3281 
3282     WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame();
3283     focusedFrame->eventHandler()->sendContextMenuEvent(PlatformMouseEvent(event, 1));
3284     ContextMenu *menu = d->page->contextMenuController()->contextMenu();
3285     // If the website defines its own handler then sendContextMenuEvent takes care of
3286     // calling/showing it and the context menu pointer will be zero. This is the case
3287     // on maps.google.com for example.
3288 
3289     return !menu;
3290 }
3291 #endif // QT_NO_CONTEXTMENU
3292 
3293 /*!
3294     Updates the page's actions depending on the position \a pos. For example if \a pos is over an image
3295     element the CopyImageToClipboard action is enabled.
3296 */
updatePositionDependentActions(const QPoint & pos)3297 void QWebPage::updatePositionDependentActions(const QPoint &pos)
3298 {
3299 #ifndef QT_NO_ACTION
3300     // First we disable all actions, but keep track of which ones were originally enabled.
3301     QBitArray originallyEnabledWebActions(QWebPage::WebActionCount);
3302     for (int i = ContextMenuItemTagNoAction; i < ContextMenuItemBaseApplicationTag; ++i) {
3303         QWebPage::WebAction action = webActionForContextMenuAction(WebCore::ContextMenuAction(i));
3304         if (QAction *a = this->action(action)) {
3305             originallyEnabledWebActions.setBit(action, a->isEnabled());
3306             a->setEnabled(false);
3307         }
3308     }
3309 #endif // QT_NO_ACTION
3310 
3311     d->createMainFrame();
3312     WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame();
3313     HitTestResult result = focusedFrame->eventHandler()->hitTestResultAtPoint(focusedFrame->view()->windowToContents(pos), /*allowShadowContent*/ false);
3314 
3315     if (result.scrollbar())
3316         d->hitTestResult = QWebHitTestResult();
3317     else
3318         d->hitTestResult = QWebHitTestResult(new QWebHitTestResultPrivate(result));
3319 
3320     d->page->contextMenuController()->setHitTestResult(result);
3321     d->page->contextMenuController()->populate();
3322 
3323 #if ENABLE(INSPECTOR)
3324     if (d->page->inspectorController()->enabled())
3325         d->page->contextMenuController()->addInspectElementItem();
3326 #endif
3327 
3328     QBitArray visitedWebActions(QWebPage::WebActionCount);
3329 
3330 #ifndef QT_NO_CONTEXTMENU
3331     delete d->currentContextMenu;
3332 
3333     // Then we let createContextMenu() enable the actions that are put into the menu
3334     d->currentContextMenu = d->createContextMenu(d->page->contextMenuController()->contextMenu(), d->page->contextMenuController()->contextMenu()->platformDescription(), &visitedWebActions);
3335 #endif // QT_NO_CONTEXTMENU
3336 
3337 #ifndef QT_NO_ACTION
3338     // Finally, we restore the original enablement for the actions that were not put into the menu.
3339     originallyEnabledWebActions &= ~visitedWebActions; // Mask out visited actions (they're part of the menu)
3340     for (int i = 0; i < QWebPage::WebActionCount; ++i) {
3341         if (originallyEnabledWebActions.at(i)) {
3342             if (QAction *a = this->action(QWebPage::WebAction(i)))
3343                 a->setEnabled(true);
3344         }
3345     }
3346 #endif // QT_NO_ACTION
3347 
3348     // This whole process ensures that any actions put into to the context menu has the right
3349     // enablement, while also keeping the correct enablement for actions that were left out of
3350     // the menu.
3351 
3352 }
3353 
3354 
3355 
3356 /*!
3357     \enum QWebPage::Extension
3358 
3359     This enum describes the types of extensions that the page can support. Before using these extensions, you
3360     should verify that the extension is supported by calling supportsExtension().
3361 
3362     \value ChooseMultipleFilesExtension Whether the web page supports multiple file selection.
3363     This extension is invoked when the web content requests one or more file names, for example
3364     as a result of the user clicking on a "file upload" button in a HTML form where multiple
3365     file selection is allowed.
3366 
3367     \value ErrorPageExtension Whether the web page can provide an error page when loading fails.
3368     (introduced in Qt 4.6)
3369 
3370     \sa ChooseMultipleFilesExtensionOption, ChooseMultipleFilesExtensionReturn, ErrorPageExtensionOption, ErrorPageExtensionReturn
3371 */
3372 
3373 /*!
3374     \enum QWebPage::ErrorDomain
3375     \since 4.6
3376 
3377     This enum describes the domain of an ErrorPageExtensionOption object (i.e. the layer in which the error occurred).
3378 
3379     \value QtNetwork The error occurred in the QtNetwork layer; the error code is of type QNetworkReply::NetworkError.
3380     \value Http The error occurred in the HTTP layer; the error code is a HTTP status code (see QNetworkRequest::HttpStatusCodeAttribute).
3381     \value WebKit The error is an internal WebKit error.
3382 */
3383 
3384 /*!
3385     \class QWebPage::ExtensionOption
3386     \since 4.4
3387     \brief The ExtensionOption class provides an extended input argument to QWebPage's extension support.
3388 
3389     \inmodule QtWebKit
3390 
3391     \sa QWebPage::extension() QWebPage::ExtensionReturn
3392 */
3393 
3394 
3395 /*!
3396     \class QWebPage::ExtensionReturn
3397     \since 4.4
3398     \brief The ExtensionReturn class provides an output result from a QWebPage's extension.
3399 
3400     \inmodule QtWebKit
3401 
3402     \sa QWebPage::extension() QWebPage::ExtensionOption
3403 */
3404 
3405 /*!
3406     \class QWebPage::ErrorPageExtensionOption
3407     \since 4.6
3408     \brief The ErrorPageExtensionOption class describes the option
3409     for the error page extension.
3410 
3411     \inmodule QtWebKit
3412 
3413     The ErrorPageExtensionOption class holds the \a url for which an error occurred as well as
3414     the associated \a frame.
3415 
3416     The error itself is reported by an error \a domain, the \a error code as well as \a errorString.
3417 
3418     \sa QWebPage::extension() QWebPage::ErrorPageExtensionReturn
3419 */
3420 
3421 /*!
3422     \variable QWebPage::ErrorPageExtensionOption::url
3423     \brief the url for which an error occurred
3424 */
3425 
3426 /*!
3427     \variable QWebPage::ErrorPageExtensionOption::frame
3428     \brief the frame associated with the error
3429 */
3430 
3431 /*!
3432     \variable QWebPage::ErrorPageExtensionOption::domain
3433     \brief the domain that reported the error
3434 */
3435 
3436 /*!
3437     \variable QWebPage::ErrorPageExtensionOption::error
3438     \brief the error code. Interpretation of the value depends on the \a domain
3439     \sa QWebPage::ErrorDomain
3440 */
3441 
3442 /*!
3443     \variable QWebPage::ErrorPageExtensionOption::errorString
3444     \brief a string that describes the error
3445 */
3446 
3447 /*!
3448     \class QWebPage::ErrorPageExtensionReturn
3449     \since 4.6
3450     \brief The ErrorPageExtensionReturn describes the error page, which will be shown for the
3451     frame for which the error occured.
3452 
3453     \inmodule QtWebKit
3454 
3455     The ErrorPageExtensionReturn class holds the data needed for creating an error page. Some are
3456     optional such as \a contentType, which defaults to "text/html", as well as the \a encoding, which
3457     is assumed to be UTF-8 if not indicated otherwise.
3458 
3459     The error page is stored in the \a content byte array, as HTML content. In order to convert a
3460     QString to a byte array, the QString::toUtf8() method can be used.
3461 
3462     External objects such as stylesheets or images referenced in the HTML are located relative to
3463     \a baseUrl.
3464 
3465     \sa QWebPage::extension() QWebPage::ErrorPageExtensionOption, QString::toUtf8()
3466 */
3467 
3468 /*!
3469     \fn QWebPage::ErrorPageExtensionReturn::ErrorPageExtensionReturn()
3470 
3471     Constructs a new error page object.
3472 */
3473 
3474 
3475 /*!
3476     \variable QWebPage::ErrorPageExtensionReturn::contentType
3477     \brief the error page's content type
3478 */
3479 
3480 /*!
3481     \variable QWebPage::ErrorPageExtensionReturn::encoding
3482     \brief the error page encoding
3483 */
3484 
3485 /*!
3486     \variable QWebPage::ErrorPageExtensionReturn::baseUrl
3487     \brief the base url
3488 
3489     External objects such as stylesheets or images referenced in the HTML are located relative to this url.
3490 */
3491 
3492 /*!
3493     \variable QWebPage::ErrorPageExtensionReturn::content
3494     \brief the HTML content of the error page
3495 */
3496 
3497 /*!
3498     \class QWebPage::ChooseMultipleFilesExtensionOption
3499     \since 4.5
3500     \brief The ChooseMultipleFilesExtensionOption class describes the option
3501     for the multiple files selection extension.
3502 
3503     \inmodule QtWebKit
3504 
3505     The ChooseMultipleFilesExtensionOption class holds the frame originating the request
3506     and the suggested filenames which might be provided.
3507 
3508     \sa QWebPage::extension() QWebPage::chooseFile(), QWebPage::ChooseMultipleFilesExtensionReturn
3509 */
3510 
3511 /*!
3512     \variable QWebPage::ChooseMultipleFilesExtensionOption::parentFrame
3513     \brief The frame in which the request originated
3514 */
3515 
3516 /*!
3517     \variable QWebPage::ChooseMultipleFilesExtensionOption::suggestedFileNames
3518     \brief The suggested filenames
3519 */
3520 
3521 /*!
3522     \variable QWebPage::ChooseMultipleFilesExtensionReturn::fileNames
3523     \brief The selected filenames
3524 */
3525 
3526 /*!
3527     \class QWebPage::ChooseMultipleFilesExtensionReturn
3528     \since 4.5
3529     \brief The ChooseMultipleFilesExtensionReturn describes the return value
3530     for the multiple files selection extension.
3531 
3532     \inmodule QtWebKit
3533 
3534     The ChooseMultipleFilesExtensionReturn class holds the filenames selected by the user
3535     when the extension is invoked.
3536 
3537     \sa QWebPage::extension() QWebPage::ChooseMultipleFilesExtensionOption
3538 */
3539 
3540 /*!
3541     This virtual function can be reimplemented in a QWebPage subclass to provide support for extensions. The \a option
3542     argument is provided as input to the extension; the output results can be stored in \a output.
3543 
3544     The behavior of this function is determined by \a extension. The \a option
3545     and \a output values are typically casted to the corresponding types (for
3546     example, ChooseMultipleFilesExtensionOption and
3547     ChooseMultipleFilesExtensionReturn for ChooseMultipleFilesExtension).
3548 
3549     You can call supportsExtension() to check if an extension is supported by the page.
3550 
3551     Returns true if the extension was called successfully; otherwise returns false.
3552 
3553     \sa supportsExtension(), Extension
3554 */
extension(Extension extension,const ExtensionOption * option,ExtensionReturn * output)3555 bool QWebPage::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
3556 {
3557 #ifndef QT_NO_FILEDIALOG
3558     if (extension == ChooseMultipleFilesExtension) {
3559         // FIXME: do not ignore suggestedFiles
3560         QStringList suggestedFiles = static_cast<const ChooseMultipleFilesExtensionOption*>(option)->suggestedFileNames;
3561         QWidget* parent = (d->client) ? d->client->ownerWidget() : 0;
3562         QStringList names = QFileDialog::getOpenFileNames(parent, QString::null);
3563         static_cast<ChooseMultipleFilesExtensionReturn*>(output)->fileNames = names;
3564         return true;
3565     }
3566 #endif
3567 
3568     return false;
3569 }
3570 
3571 /*!
3572     This virtual function returns true if the web page supports \a extension; otherwise false is returned.
3573 
3574     \sa extension()
3575 */
supportsExtension(Extension extension) const3576 bool QWebPage::supportsExtension(Extension extension) const
3577 {
3578 #ifndef QT_NO_FILEDIALOG
3579     return extension == ChooseMultipleFilesExtension;
3580 #else
3581     Q_UNUSED(extension);
3582     return false;
3583 #endif
3584 }
3585 
3586 /*!
3587     Finds the specified string, \a subString, in the page, using the given \a options.
3588 
3589     If the HighlightAllOccurrences flag is passed, the function will highlight all occurrences
3590     that exist in the page. All subsequent calls will extend the highlight, rather than
3591     replace it, with occurrences of the new string.
3592 
3593     If the HighlightAllOccurrences flag is not passed, the function will select an occurrence
3594     and all subsequent calls will replace the current occurrence with the next one.
3595 
3596     To clear the selection, just pass an empty string.
3597 
3598     Returns true if \a subString was found; otherwise returns false.
3599 */
findText(const QString & subString,FindFlags options)3600 bool QWebPage::findText(const QString &subString, FindFlags options)
3601 {
3602     ::TextCaseSensitivity caseSensitivity = ::TextCaseInsensitive;
3603     if (options & FindCaseSensitively)
3604         caseSensitivity = ::TextCaseSensitive;
3605 
3606     if (options & HighlightAllOccurrences) {
3607         if (subString.isEmpty()) {
3608             d->page->unmarkAllTextMatches();
3609             return true;
3610         } else
3611             return d->page->markAllMatchesForText(subString, caseSensitivity, true, 0);
3612     } else {
3613         if (subString.isEmpty()) {
3614             d->page->mainFrame()->selection()->clear();
3615             Frame* frame = d->page->mainFrame()->tree()->firstChild();
3616             while (frame) {
3617                 frame->selection()->clear();
3618                 frame = frame->tree()->traverseNextWithWrap(false);
3619             }
3620         }
3621         ::FindDirection direction = ::FindDirectionForward;
3622         if (options & FindBackward)
3623             direction = ::FindDirectionBackward;
3624 
3625         const bool shouldWrap = options & FindWrapsAroundDocument;
3626 
3627         return d->page->findString(subString, caseSensitivity, direction, shouldWrap);
3628     }
3629 }
3630 
3631 /*!
3632     Returns a pointer to the page's settings object.
3633 
3634     \sa QWebSettings::globalSettings()
3635 */
settings() const3636 QWebSettings *QWebPage::settings() const
3637 {
3638     return d->settings;
3639 }
3640 
3641 /*!
3642     This function is called when the web content requests a file name, for example
3643     as a result of the user clicking on a "file upload" button in a HTML form.
3644 
3645     A suggested filename may be provided in \a suggestedFile. The frame originating the
3646     request is provided as \a parentFrame.
3647 
3648     \sa ChooseMultipleFilesExtension
3649 */
chooseFile(QWebFrame * parentFrame,const QString & suggestedFile)3650 QString QWebPage::chooseFile(QWebFrame *parentFrame, const QString& suggestedFile)
3651 {
3652     Q_UNUSED(parentFrame)
3653 #ifndef QT_NO_FILEDIALOG
3654     QWidget* parent = (d->client) ? d->client->ownerWidget() : 0;
3655     return QFileDialog::getOpenFileName(parent, QString::null, suggestedFile);
3656 #else
3657     return QString::null;
3658 #endif
3659 }
3660 
3661 /*!
3662     Sets the QNetworkAccessManager \a manager responsible for serving network requests for this
3663     QWebPage.
3664 
3665     \note It is currently not supported to change the network access manager after the
3666     QWebPage has used it. The results of doing this are undefined.
3667 
3668     \sa networkAccessManager()
3669 */
setNetworkAccessManager(QNetworkAccessManager * manager)3670 void QWebPage::setNetworkAccessManager(QNetworkAccessManager *manager)
3671 {
3672     if (manager == d->networkManager)
3673         return;
3674     if (d->networkManager && d->networkManager->parent() == this)
3675         delete d->networkManager;
3676     d->networkManager = manager;
3677 }
3678 
3679 /*!
3680     Returns the QNetworkAccessManager that is responsible for serving network
3681     requests for this QWebPage.
3682 
3683     \sa setNetworkAccessManager()
3684 */
networkAccessManager() const3685 QNetworkAccessManager *QWebPage::networkAccessManager() const
3686 {
3687     if (!d->networkManager) {
3688         QWebPage *that = const_cast<QWebPage *>(this);
3689         that->d->networkManager = new QNetworkAccessManager(that);
3690     }
3691     return d->networkManager;
3692 }
3693 
3694 /*!
3695     Sets the QWebPluginFactory \a factory responsible for creating plugins embedded into this
3696     QWebPage.
3697 
3698     Note: The plugin factory is only used if the QWebSettings::PluginsEnabled attribute is enabled.
3699 
3700     \sa pluginFactory()
3701 */
setPluginFactory(QWebPluginFactory * factory)3702 void QWebPage::setPluginFactory(QWebPluginFactory *factory)
3703 {
3704     d->pluginFactory = factory;
3705 }
3706 
3707 /*!
3708     Returns the QWebPluginFactory that is responsible for creating plugins embedded into
3709     this QWebPage. If no plugin factory is installed a null pointer is returned.
3710 
3711     \sa setPluginFactory()
3712 */
pluginFactory() const3713 QWebPluginFactory *QWebPage::pluginFactory() const
3714 {
3715     return d->pluginFactory;
3716 }
3717 
3718 /*!
3719     This function is called when a user agent for HTTP requests is needed. You can reimplement this
3720     function to dynamically return different user agents for different URLs, based on the \a url parameter.
3721 
3722     The default implementation returns the following value:
3723 
3724     "Mozilla/5.0 (%Platform%%Security%%Subplatform%) AppleWebKit/%WebKitVersion% (KHTML, like Gecko) %AppVersion Safari/%WebKitVersion%"
3725 
3726     On mobile platforms such as Symbian S60 and Maemo, "Mobile Safari" is used instead of "Safari".
3727 
3728     In this string the following values are replaced at run-time:
3729     \list
3730     \o %Platform% expands to the windowing system followed by "; " if it is not Windows (e.g. "X11; ").
3731     \o %Security% expands to "N; " if SSL is disabled.
3732     \o %Subplatform% expands to the operating system version (e.g. "Windows NT 6.1" or "Intel Mac OS X 10.5").
3733     \o %WebKitVersion% is the version of WebKit the application was compiled against.
3734     \o %AppVersion% expands to QCoreApplication::applicationName()/QCoreApplication::applicationVersion() if they're set; otherwise defaulting to Qt and the current Qt version.
3735     \endlist
3736 */
userAgentForUrl(const QUrl &) const3737 QString QWebPage::userAgentForUrl(const QUrl&) const
3738 {
3739     // splitting the string in three and user QStringBuilder is better than using QString::arg()
3740     static QString firstPart;
3741     static QString secondPart;
3742     static QString thirdPart;
3743 
3744     if (firstPart.isNull() || secondPart.isNull() || thirdPart.isNull()) {
3745         QString firstPartTemp;
3746         firstPartTemp.reserve(150);
3747         firstPartTemp += QString::fromLatin1("Mozilla/5.0 ("
3748 
3749     // Platform
3750 #ifdef Q_WS_MAC
3751         "Macintosh; "
3752 #elif defined Q_WS_QWS
3753         "QtEmbedded; "
3754 #elif defined Q_WS_MAEMO_5
3755         "Maemo"
3756 #elif defined Q_WS_MAEMO_6
3757         "MeeGo"
3758 #elif defined Q_WS_WIN
3759         // Nothing
3760 #elif defined Q_WS_X11
3761         "X11; "
3762 #elif defined Q_OS_SYMBIAN
3763         "Symbian"
3764 #else
3765         "Unknown; "
3766 #endif
3767     );
3768 
3769 #if defined Q_OS_SYMBIAN
3770         QSysInfo::SymbianVersion symbianVersion = QSysInfo::symbianVersion();
3771         switch (symbianVersion) {
3772         case QSysInfo::SV_9_2:
3773             firstPartTemp += QString::fromLatin1("OS/9.2; ");
3774             break;
3775         case QSysInfo::SV_9_3:
3776             firstPartTemp += QString::fromLatin1("OS/9.3; ");
3777             break;
3778         case QSysInfo::SV_9_4:
3779             firstPartTemp += QString::fromLatin1("OS/9.4; ");
3780             break;
3781         case QSysInfo::SV_SF_2:
3782             firstPartTemp += QString::fromLatin1("/2; ");
3783             break;
3784         case QSysInfo::SV_SF_3:
3785             firstPartTemp += QString::fromLatin1("/3; ");
3786             break;
3787         case QSysInfo::SV_SF_4:
3788             firstPartTemp += QString::fromLatin1("/4; ");
3789             break;
3790         default:
3791             firstPartTemp += QString::fromLatin1("; ");
3792             break;
3793         }
3794 #endif
3795 
3796 #if defined(QT_NO_OPENSSL)
3797         // No SSL support
3798         firstPartTemp += QString::fromLatin1("N; ");
3799 #endif
3800 
3801         // Operating system
3802 #ifdef Q_OS_AIX
3803         firstPartTemp += QString::fromLatin1("AIX");
3804 #elif defined Q_OS_WIN32
3805         firstPartTemp += windowsVersionForUAString();
3806 #elif defined Q_OS_DARWIN
3807 #if CPU(X86) || CPU(X86_64)
3808         firstPartTemp += QString::fromLatin1("Intel Mac OS X");
3809 #else
3810         firstPartTemp += QString::fromLatin1("PPC Mac OS X");
3811 #endif
3812 
3813 #elif defined Q_OS_BSDI
3814         firstPartTemp += QString::fromLatin1("BSD");
3815 #elif defined Q_OS_BSD4
3816         firstPartTemp += QString::fromLatin1("BSD Four");
3817 #elif defined Q_OS_CYGWIN
3818         firstPartTemp += QString::fromLatin1("Cygwin");
3819 #elif defined Q_OS_DGUX
3820         firstPartTemp += QString::fromLatin1("DG/UX");
3821 #elif defined Q_OS_DYNIX
3822         firstPartTemp += QString::fromLatin1("DYNIX/ptx");
3823 #elif defined Q_OS_FREEBSD
3824         firstPartTemp += QString::fromLatin1("FreeBSD");
3825 #elif defined Q_OS_HPUX
3826         firstPartTemp += QString::fromLatin1("HP-UX");
3827 #elif defined Q_OS_HURD
3828         firstPartTemp += QString::fromLatin1("GNU Hurd");
3829 #elif defined Q_OS_IRIX
3830         firstPartTemp += QString::fromLatin1("SGI Irix");
3831 #elif defined Q_OS_LINUX
3832 #if !defined(Q_WS_MAEMO_5) && !defined(Q_WS_MAEMO_6)
3833 
3834 #if defined(__x86_64__)
3835         firstPartTemp += QString::fromLatin1("Linux x86_64");
3836 #elif defined(__i386__)
3837         firstPartTemp += QString::fromLatin1("Linux i686");
3838 #else
3839         firstPartTemp += QString::fromLatin1("Linux");
3840 #endif
3841 #endif
3842 
3843 #elif defined Q_OS_LYNX
3844         firstPartTemp += QString::fromLatin1("LynxOS");
3845 #elif defined Q_OS_NETBSD
3846         firstPartTemp += QString::fromLatin1("NetBSD");
3847 #elif defined Q_OS_OS2
3848         firstPartTemp += QString::fromLatin1("OS/2");
3849 #elif defined Q_OS_OPENBSD
3850         firstPartTemp += QString::fromLatin1("OpenBSD");
3851 #elif defined Q_OS_OS2EMX
3852         firstPartTemp += QString::fromLatin1("OS/2");
3853 #elif defined Q_OS_OSF
3854         firstPartTemp += QString::fromLatin1("HP Tru64 UNIX");
3855 #elif defined Q_OS_QNX6
3856         firstPartTemp += QString::fromLatin1("QNX RTP Six");
3857 #elif defined Q_OS_QNX
3858         firstPartTemp += QString::fromLatin1("QNX");
3859 #elif defined Q_OS_RELIANT
3860         firstPartTemp += QString::fromLatin1("Reliant UNIX");
3861 #elif defined Q_OS_SCO
3862         firstPartTemp += QString::fromLatin1("SCO OpenServer");
3863 #elif defined Q_OS_SOLARIS
3864         firstPartTemp += QString::fromLatin1("Sun Solaris");
3865 #elif defined Q_OS_ULTRIX
3866         firstPartTemp += QString::fromLatin1("DEC Ultrix");
3867 #elif defined Q_OS_SYMBIAN
3868         firstPartTemp += QLatin1Char(' ');
3869         QSysInfo::S60Version s60Version = QSysInfo::s60Version();
3870         switch (s60Version) {
3871         case QSysInfo::SV_S60_3_1:
3872             firstPartTemp += QString::fromLatin1("Series60/3.1");
3873             break;
3874         case QSysInfo::SV_S60_3_2:
3875             firstPartTemp += QString::fromLatin1("Series60/3.2");
3876             break;
3877         case QSysInfo::SV_S60_5_0:
3878             firstPartTemp += QString::fromLatin1("Series60/5.0");
3879             break;
3880         default:
3881             break;
3882         }
3883 #elif defined Q_OS_UNIX
3884         firstPartTemp += QString::fromLatin1("UNIX BSD/SYSV system");
3885 #elif defined Q_OS_UNIXWARE
3886         firstPartTemp += QString::fromLatin1("UnixWare Seven, Open UNIX Eight");
3887 #else
3888         firstPartTemp += QString::fromLatin1("Unknown");
3889 #endif
3890 
3891 #if USE(QT_MOBILITY_SYSTEMINFO)
3892         // adding Model Number
3893         QtMobility::QSystemDeviceInfo systemDeviceInfo;
3894 
3895         QString model = systemDeviceInfo.model();
3896         if (!model.isEmpty()) {
3897             if (!firstPartTemp.endsWith("; "))
3898                 firstPartTemp += QString::fromLatin1("; ");
3899             firstPartTemp += systemDeviceInfo.model();
3900         }
3901 #endif
3902         firstPartTemp.squeeze();
3903         firstPart = firstPartTemp;
3904 
3905         QString secondPartTemp;
3906         secondPartTemp.reserve(150);
3907         secondPartTemp += QString::fromLatin1(") ");
3908 
3909         // webkit/qt version
3910         secondPartTemp += QString::fromLatin1("AppleWebKit/");
3911         secondPartTemp += qWebKitVersion();
3912         secondPartTemp += QString::fromLatin1(" (KHTML, like Gecko) ");
3913 
3914 
3915         // Application name split the third part
3916         secondPartTemp.squeeze();
3917         secondPart = secondPartTemp;
3918 
3919         QString thirdPartTemp;
3920         thirdPartTemp.reserve(150);
3921 #if defined(Q_OS_SYMBIAN) || defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
3922         thirdPartTemp += QLatin1String(" Mobile Safari/");
3923 #else
3924         thirdPartTemp += QLatin1String(" Safari/");
3925 #endif
3926         thirdPartTemp += qWebKitVersion();
3927         thirdPartTemp.squeeze();
3928         thirdPart = thirdPartTemp;
3929         Q_ASSERT(!firstPart.isNull());
3930         Q_ASSERT(!secondPart.isNull());
3931         Q_ASSERT(!thirdPart.isNull());
3932     }
3933 
3934     // Application name/version
3935     QString appName = QCoreApplication::applicationName();
3936     if (!appName.isEmpty()) {
3937         QString appVer = QCoreApplication::applicationVersion();
3938         if (!appVer.isEmpty())
3939             appName.append(QLatin1Char('/') + appVer);
3940     } else {
3941         // Qt version
3942         appName = QString::fromLatin1("Qt/") + QString::fromLatin1(qVersion());
3943     }
3944 
3945     return firstPart + secondPart + appName + thirdPart;
3946 }
3947 
3948 
_q_onLoadProgressChanged(int)3949 void QWebPagePrivate::_q_onLoadProgressChanged(int)
3950 {
3951     m_totalBytes = page->progress()->totalPageAndResourceBytesToLoad();
3952     m_bytesReceived = page->progress()->totalBytesReceived();
3953 }
3954 
3955 
3956 /*!
3957     Returns the total number of bytes that were received from the network to render the current page,
3958     including extra content such as embedded images.
3959 
3960     \sa bytesReceived()
3961 */
totalBytes() const3962 quint64 QWebPage::totalBytes() const
3963 {
3964     return d->m_totalBytes;
3965 }
3966 
3967 
3968 /*!
3969     Returns the number of bytes that were received from the network to render the current page.
3970 
3971     \sa totalBytes(), loadProgress()
3972 */
bytesReceived() const3973 quint64 QWebPage::bytesReceived() const
3974 {
3975     return d->m_bytesReceived;
3976 }
3977 
3978 /*!
3979     \since 4.8
3980     \fn void QWebPage::viewportChangeRequested()
3981 
3982     Page authors can provide the supplied values by using the viewport meta tag. More information
3983     about this can be found at \l{http://developer.apple.com/safari/library/documentation/appleapplications/reference/safariwebcontent/usingtheviewport/usingtheviewport.html}{Safari Reference Library: Using the Viewport Meta Tag}.
3984 
3985     \sa QWebPage::ViewportAttributes, setPreferredContentsSize(), QGraphicsWebView::setScale()
3986 */
3987 
3988 /*!
3989     \fn void QWebPage::loadStarted()
3990 
3991     This signal is emitted when a page starts loading content.
3992 
3993     \sa loadFinished()
3994 */
3995 
3996 /*!
3997     \fn void QWebPage::loadProgress(int progress)
3998 
3999     This signal is emitted when the global progress status changes.
4000     The current value is provided by \a progress and scales from 0 to 100,
4001     which is the default range of QProgressBar.
4002     It accumulates changes from all the child frames.
4003 
4004     \sa bytesReceived()
4005 */
4006 
4007 /*!
4008     \fn void QWebPage::loadFinished(bool ok)
4009 
4010     This signal is emitted when the page finishes loading content. This signal
4011     is independant of script execution or page rendering.
4012     \a ok will indicate whether the load was successful or any error occurred.
4013 
4014     \sa loadStarted(), ErrorPageExtension
4015 */
4016 
4017 /*!
4018     \fn void QWebPage::linkHovered(const QString &link, const QString &title, const QString &textContent)
4019 
4020     This signal is emitted when the mouse hovers over a link.
4021 
4022     \a link contains the link url.
4023     \a title is the link element's title, if it is specified in the markup.
4024     \a textContent provides text within the link element, e.g., text inside an HTML anchor tag.
4025 
4026     When the mouse leaves the link element the signal is emitted with empty parameters.
4027 
4028     \sa linkClicked()
4029 */
4030 
4031 /*!
4032     \fn void QWebPage::statusBarMessage(const QString& text)
4033 
4034     This signal is emitted when the statusbar \a text is changed by the page.
4035 */
4036 
4037 /*!
4038     \fn void QWebPage::frameCreated(QWebFrame *frame)
4039 
4040     This signal is emitted whenever the page creates a new \a frame.
4041 
4042     \sa currentFrame()
4043 */
4044 
4045 /*!
4046     \fn void QWebPage::selectionChanged()
4047 
4048     This signal is emitted whenever the selection changes, either interactively
4049     or programmatically (e.g. by calling triggerAction() with a selection action).
4050 
4051     \sa selectedText()
4052 */
4053 
4054 /*!
4055     \fn void QWebPage::contentsChanged()
4056     \since 4.5
4057 
4058     This signal is emitted whenever the text in form elements changes
4059     as well as other editable content.
4060 
4061     \sa contentEditable, modified, QWebFrame::toHtml(), QWebFrame::toPlainText()
4062 */
4063 
4064 /*!
4065     \fn void QWebPage::geometryChangeRequested(const QRect& geom)
4066 
4067     This signal is emitted whenever the document wants to change the position and size of the
4068     page to \a geom. This can happen for example through JavaScript.
4069 */
4070 
4071 /*!
4072     \fn void QWebPage::repaintRequested(const QRect& dirtyRect)
4073 
4074     This signal is emitted whenever this QWebPage should be updated. It's useful
4075     when rendering a QWebPage without a QWebView or QGraphicsWebView.
4076     \a dirtyRect contains the area that needs to be updated. To paint the QWebPage get
4077     the mainFrame() and call the render(QPainter*, const QRegion&) method with the
4078     \a dirtyRect as the second parameter.
4079 
4080     \sa mainFrame()
4081     \sa view()
4082 */
4083 
4084 /*!
4085     \fn void QWebPage::scrollRequested(int dx, int dy, const QRect& rectToScroll)
4086 
4087     This signal is emitted whenever the content given by \a rectToScroll needs
4088     to be scrolled \a dx and \a dy downwards and no view was set.
4089 
4090     \sa view()
4091 */
4092 
4093 /*!
4094     \fn void QWebPage::windowCloseRequested()
4095 
4096     This signal is emitted whenever the page requests the web browser window to be closed,
4097     for example through the JavaScript \c{window.close()} call.
4098 */
4099 
4100 /*!
4101     \fn void QWebPage::printRequested(QWebFrame *frame)
4102 
4103     This signal is emitted whenever the page requests the web browser to print \a frame,
4104     for example through the JavaScript \c{window.print()} call.
4105 
4106     \sa QWebFrame::print(), QPrintPreviewDialog
4107 */
4108 
4109 /*!
4110     \fn void QWebPage::unsupportedContent(QNetworkReply *reply)
4111 
4112     This signal is emitted when WebKit cannot handle a link the user navigated to or a
4113     web server's response includes a "Content-Disposition" header with the 'attachment'
4114     directive. If "Content-Disposition" is present in \a reply, the web server is indicating
4115     that the client should prompt the user to save the content regardless of content-type.
4116     See RFC 2616 sections 19.5.1 for details about Content-Disposition.
4117 
4118     At signal emission time the meta-data of the QNetworkReply \a reply is available.
4119 
4120     \note The receiving slot is responsible for deleting the QNetworkReply \a reply.
4121 
4122     \note This signal is only emitted if the forwardUnsupportedContent property is set to true.
4123 
4124     \sa downloadRequested()
4125 */
4126 
4127 /*!
4128     \fn void QWebPage::downloadRequested(const QNetworkRequest &request)
4129 
4130     This signal is emitted when the user decides to download a link. The url of
4131     the link as well as additional meta-information is contained in \a request.
4132 
4133     \sa unsupportedContent()
4134 */
4135 
4136 /*!
4137     \fn void QWebPage::microFocusChanged()
4138 
4139     This signal is emitted when for example the position of the cursor in an editable form
4140     element changes. It is used to inform input methods about the new on-screen position where
4141     the user is able to enter text. This signal is usually connected to the
4142     QWidget::updateMicroFocus() slot.
4143 */
4144 
4145 /*!
4146     \fn void QWebPage::linkClicked(const QUrl &url)
4147 
4148     This signal is emitted whenever the user clicks on a link and the page's linkDelegationPolicy
4149     property is set to delegate the link handling for the specified \a url.
4150 
4151     By default no links are delegated and are handled by QWebPage instead.
4152 
4153     \note This signal possibly won't be emitted for clicked links which use
4154     JavaScript to trigger navigation.
4155 
4156     \sa linkHovered()
4157 */
4158 
4159 /*!
4160     \fn void QWebPage::toolBarVisibilityChangeRequested(bool visible)
4161 
4162     This signal is emitted whenever the visibility of the toolbar in a web browser
4163     window that hosts QWebPage should be changed to \a visible.
4164 */
4165 
4166 /*!
4167     \fn void QWebPage::statusBarVisibilityChangeRequested(bool visible)
4168 
4169     This signal is emitted whenever the visibility of the statusbar in a web browser
4170     window that hosts QWebPage should be changed to \a visible.
4171 */
4172 
4173 /*!
4174     \fn void QWebPage::menuBarVisibilityChangeRequested(bool visible)
4175 
4176     This signal is emitted whenever the visibility of the menubar in a web browser
4177     window that hosts QWebPage should be changed to \a visible.
4178 */
4179 
4180 /*!
4181     \fn void QWebPage::databaseQuotaExceeded(QWebFrame* frame, QString databaseName);
4182     \since 4.5
4183 
4184     This signal is emitted whenever the web site shown in \a frame is asking to store data
4185     to the database \a databaseName and the quota allocated to that web site is exceeded.
4186 
4187     \sa QWebDatabase
4188 */
4189 /*!
4190     \fn void QWebPage::applicationCacheQuotaExceeded(QWebSecurityOrigin* origin, quint64 defaultOriginQuota);
4191 
4192     This signal is emitted whenever the web site is asking to store data to the application cache
4193     database databaseName and the quota allocated to that web site is exceeded.
4194 
4195 */
4196 
4197 /*!
4198   \since 4.5
4199   \fn void QWebPage::saveFrameStateRequested(QWebFrame* frame, QWebHistoryItem* item);
4200 
4201   This signal is emitted shortly before the history of navigated pages
4202   in \a frame is changed, for example when navigating back in the history.
4203 
4204   The provided QWebHistoryItem, \a item, holds the history entry of the frame before
4205   the change.
4206 
4207   A potential use-case for this signal is to store custom data in
4208   the QWebHistoryItem associated to the frame, using QWebHistoryItem::setUserData().
4209 */
4210 
4211 /*!
4212   \since 4.5
4213   \fn void QWebPage::restoreFrameStateRequested(QWebFrame* frame);
4214 
4215   This signal is emitted when the load of \a frame is finished and the application may now update its state accordingly.
4216 */
4217 
4218 /*!
4219   \fn QWebPagePrivate* QWebPage::handle() const
4220   \internal
4221 */
4222 
4223 #include "moc_qwebpage.cpp"
4224