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