• 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 #include "qwebview.h"
25 #include "qwebframe.h"
26 #include "qwebpage_p.h"
27 #include "qwebframe_p.h"
28 #include "qwebhistory.h"
29 #include "qwebhistory_p.h"
30 #include "qwebsettings.h"
31 #include "qwebkitversion.h"
32 
33 #include "Frame.h"
34 #include "FrameTree.h"
35 #include "FrameLoader.h"
36 #include "FrameLoaderClientQt.h"
37 #include "FrameView.h"
38 #include "FormState.h"
39 #include "ApplicationCacheStorage.h"
40 #include "ChromeClientQt.h"
41 #include "ContextMenu.h"
42 #include "ContextMenuClientQt.h"
43 #include "DocumentLoader.h"
44 #include "DragClientQt.h"
45 #include "DragController.h"
46 #include "DragData.h"
47 #include "EditorClientQt.h"
48 #include "SecurityOrigin.h"
49 #include "Settings.h"
50 #include "Page.h"
51 #include "Pasteboard.h"
52 #include "FrameLoader.h"
53 #include "FrameLoadRequest.h"
54 #include "KURL.h"
55 #include "Logging.h"
56 #include "Image.h"
57 #include "InspectorClientQt.h"
58 #include "InspectorController.h"
59 #include "FocusController.h"
60 #include "Editor.h"
61 #include "Scrollbar.h"
62 #include "PlatformKeyboardEvent.h"
63 #include "PlatformWheelEvent.h"
64 #include "PluginDatabase.h"
65 #include "ProgressTracker.h"
66 #include "RefPtr.h"
67 #include "HashMap.h"
68 #include "HTMLFormElement.h"
69 #include "HitTestResult.h"
70 #include "WindowFeatures.h"
71 #include "LocalizedStrings.h"
72 #include "Cache.h"
73 #include "runtime/InitializeThreading.h"
74 
75 #include <QApplication>
76 #include <QBasicTimer>
77 #include <QBitArray>
78 #include <QDebug>
79 #include <QDesktopServices>
80 #include <QDragEnterEvent>
81 #include <QDragLeaveEvent>
82 #include <QDragMoveEvent>
83 #include <QDropEvent>
84 #include <QFileDialog>
85 #include <QHttpRequestHeader>
86 #include <QInputDialog>
87 #include <QLocale>
88 #include <QMessageBox>
89 #include <QNetworkProxy>
90 #include <QUndoStack>
91 #include <QUrl>
92 #include <QPainter>
93 #include <QClipboard>
94 #include <QSslSocket>
95 #include <QStyle>
96 #include <QSysInfo>
97 #if QT_VERSION >= 0x040400
98 #include <QNetworkAccessManager>
99 #include <QNetworkRequest>
100 #else
101 #include "qwebnetworkinterface.h"
102 #endif
103 
104 using namespace WebCore;
105 
qt_drt_overwritePluginDirectories()106 void QWEBKIT_EXPORT qt_drt_overwritePluginDirectories()
107 {
108     PluginDatabase* db = PluginDatabase::installedPlugins(/* populate */ false);
109 
110     Vector<String> paths;
111     String qtPath(getenv("QTWEBKIT_PLUGIN_PATH"));
112     qtPath.split(UChar(':'), /* allowEmptyEntries */ false, paths);
113 
114     db->setPluginDirectories(paths);
115     db->refresh();
116 }
117 
118 bool QWebPagePrivate::drtRun = false;
qt_drt_run(bool b)119 void QWEBKIT_EXPORT qt_drt_run(bool b)
120 {
121     QWebPagePrivate::drtRun = b;
122 }
123 
qt_webpage_setGroupName(QWebPage * page,const QString & groupName)124 void QWEBKIT_EXPORT qt_webpage_setGroupName(QWebPage* page, const QString& groupName)
125 {
126     page->handle()->page->setGroupName(groupName);
127 }
128 
qt_webpage_groupName(QWebPage * page)129 QString QWEBKIT_EXPORT qt_webpage_groupName(QWebPage* page)
130 {
131     return page->handle()->page->groupName();
132 }
133 
134 // Lookup table mapping QWebPage::WebActions to the associated Editor commands
135 static const char* editorCommandWebActions[] =
136 {
137     0, // OpenLink,
138 
139     0, // OpenLinkInNewWindow,
140     0, // OpenFrameInNewWindow,
141 
142     0, // DownloadLinkToDisk,
143     0, // CopyLinkToClipboard,
144 
145     0, // OpenImageInNewWindow,
146     0, // DownloadImageToDisk,
147     0, // CopyImageToClipboard,
148 
149     0, // Back,
150     0, // Forward,
151     0, // Stop,
152     0, // Reload,
153 
154     "Cut", // Cut,
155     "Copy", // Copy,
156     "Paste", // Paste,
157 
158     "Undo", // Undo,
159     "Redo", // Redo,
160     "MoveForward", // MoveToNextChar,
161     "MoveBackward", // MoveToPreviousChar,
162     "MoveWordForward", // MoveToNextWord,
163     "MoveWordBackward", // MoveToPreviousWord,
164     "MoveDown", // MoveToNextLine,
165     "MoveUp", // MoveToPreviousLine,
166     "MoveToBeginningOfLine", // MoveToStartOfLine,
167     "MoveToEndOfLine", // MoveToEndOfLine,
168     "MoveToBeginningOfParagraph", // MoveToStartOfBlock,
169     "MoveToEndOfParagraph", // MoveToEndOfBlock,
170     "MoveToBeginningOfDocument", // MoveToStartOfDocument,
171     "MoveToEndOfDocument", // MoveToEndOfDocument,
172     "MoveForwardAndModifySelection", // SelectNextChar,
173     "MoveBackwardAndModifySelection", // SelectPreviousChar,
174     "MoveWordForwardAndModifySelection", // SelectNextWord,
175     "MoveWordBackwardAndModifySelection", // SelectPreviousWord,
176     "MoveDownAndModifySelection", // SelectNextLine,
177     "MoveUpAndModifySelection", // SelectPreviousLine,
178     "MoveToBeginningOfLineAndModifySelection", // SelectStartOfLine,
179     "MoveToEndOfLineAndModifySelection", // SelectEndOfLine,
180     "MoveToBeginningOfParagraphAndModifySelection", // SelectStartOfBlock,
181     "MoveToEndOfParagraphAndModifySelection", // SelectEndOfBlock,
182     "MoveToBeginningOfDocumentAndModifySelection", //SelectStartOfDocument,
183     "MoveToEndOfDocumentAndModifySelection", // SelectEndOfDocument,
184     "DeleteWordBackward", // DeleteStartOfWord,
185     "DeleteWordForward", // DeleteEndOfWord,
186 
187     0, // SetTextDirectionDefault,
188     0, // SetTextDirectionLeftToRight,
189     0, // SetTextDirectionRightToLeft,
190 
191     "ToggleBold", // ToggleBold,
192     "ToggleItalic", // ToggleItalic,
193     "ToggleUnderline", // ToggleUnderline,
194 
195     0, // InspectElement,
196 
197     "InsertNewline", // InsertParagraphSeparator
198     "InsertLineBreak", // InsertLineSeparator
199 
200     "SelectAll", // SelectAll
201     0, // ReloadAndBypassCache,
202 
203     "PasteAndMatchStyle", // PasteAndMatchStyle
204     "RemoveFormat", // RemoveFormat
205     "Strikethrough", // ToggleStrikethrough,
206     "Subscript", // ToggleSubscript
207     "Superscript", // ToggleSuperscript
208     "InsertUnorderedList", // InsertUnorderedList
209     "InsertOrderedList", // InsertOrderedList
210     "Indent", // Indent
211     "Outdent", // Outdent,
212 
213     "AlignCenter", // AlignCenter,
214     "AlignJustified", // AlignJustified,
215     "AlignLeft", // AlignLeft,
216     "AlignRight", // AlignRight,
217 
218     0 // WebActionCount
219 };
220 
221 // Lookup the appropriate editor command to use for WebAction \a action
editorCommandForWebActions(QWebPage::WebAction action)222 const char* QWebPagePrivate::editorCommandForWebActions(QWebPage::WebAction action)
223 {
224     if ((action > QWebPage::NoWebAction) && (action < int(sizeof(editorCommandWebActions) / sizeof(const char*))))
225         return editorCommandWebActions[action];
226     return 0;
227 }
228 
229 #ifndef QT_NO_CURSOR
SetCursorEvent(const QCursor & cursor)230 SetCursorEvent::SetCursorEvent(const QCursor& cursor)
231     : QEvent(static_cast<QEvent::Type>(EventType))
232     , m_cursor(cursor)
233 {}
234 
cursor() const235 QCursor SetCursorEvent::cursor() const
236 {
237     return m_cursor;
238 }
239 #endif
240 
241 // If you change this make sure to also adjust the docs for QWebPage::userAgentForUrl
242 #define WEBKIT_VERSION "527+"
243 
dropActionToDragOp(Qt::DropActions actions)244 static inline DragOperation dropActionToDragOp(Qt::DropActions actions)
245 {
246     unsigned result = 0;
247     if (actions & Qt::CopyAction)
248         result |= DragOperationCopy;
249     if (actions & Qt::MoveAction)
250         result |= DragOperationMove;
251     if (actions & Qt::LinkAction)
252         result |= DragOperationLink;
253     return (DragOperation)result;
254 }
255 
dragOpToDropAction(unsigned actions)256 static inline Qt::DropAction dragOpToDropAction(unsigned actions)
257 {
258     Qt::DropAction result = Qt::IgnoreAction;
259     if (actions & DragOperationCopy)
260         result = Qt::CopyAction;
261     else if (actions & DragOperationMove)
262         result = Qt::MoveAction;
263     else if (actions & DragOperationLink)
264         result = Qt::LinkAction;
265     return result;
266 }
267 
initializeApplicationCachePathIfNecessary()268 static void initializeApplicationCachePathIfNecessary()
269 {
270 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
271     static bool initialized = false;
272 
273     if (initialized)
274         return;
275 
276     // Determine the path for HTML5 Application Cache DB
277     QString appCachePath;
278 #if QT_VERSION >= 0x040500
279     appCachePath = QDesktopServices::storageLocation(QDesktopServices::CacheLocation);
280 #else
281     appCachePath = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
282 #endif
283 
284     if (appCachePath.isEmpty())
285         appCachePath = QDir::homePath() + QLatin1String("/.") + QCoreApplication::applicationName();
286 
287     WebCore::cacheStorage().setCacheDirectory(appCachePath);
288     initialized = true;
289 #endif
290 }
291 
QWebPagePrivate(QWebPage * qq)292 QWebPagePrivate::QWebPagePrivate(QWebPage *qq)
293     : q(qq)
294     , view(0)
295     , viewportSize(QSize(0, 0))
296 {
297     WebCore::InitializeLoggingChannelsIfNecessary();
298     JSC::initializeThreading();
299     WebCore::FrameLoader::setLocalLoadPolicy(WebCore::FrameLoader::AllowLocalLoadsForLocalAndSubstituteData);
300     initializeApplicationCachePathIfNecessary();
301 
302     chromeClient = new ChromeClientQt(q);
303     contextMenuClient = new ContextMenuClientQt();
304     editorClient = new EditorClientQt(q);
305     page = new Page(chromeClient, contextMenuClient, editorClient,
306                     new DragClientQt(q), new InspectorClientQt(q));
307 
308     // ### should be configurable
309     page->settings()->setDefaultTextEncodingName("iso-8859-1");
310 
311     settings = new QWebSettings(page->settings());
312 
313 #ifndef QT_NO_UNDOSTACK
314     undoStack = 0;
315 #endif
316     mainFrame = 0;
317 #if QT_VERSION < 0x040400
318     networkInterface = 0;
319 #else
320     networkManager = 0;
321 #endif
322     pluginFactory = 0;
323     insideOpenCall = false;
324     forwardUnsupportedContent = false;
325     editable = false;
326     useFixedLayout = false;
327     linkPolicy = QWebPage::DontDelegateLinks;
328 #ifndef QT_NO_CONTEXTMENU
329     currentContextMenu = 0;
330 #endif
331 
332     history.d = new QWebHistoryPrivate(page->backForwardList());
333     memset(actions, 0, sizeof(actions));
334 }
335 
~QWebPagePrivate()336 QWebPagePrivate::~QWebPagePrivate()
337 {
338 #ifndef QT_NO_CONTEXTMENU
339     delete currentContextMenu;
340 #endif
341 #ifndef QT_NO_UNDOSTACK
342     delete undoStack;
343 #endif
344     delete settings;
345     delete page;
346 }
347 
348 #if QT_VERSION < 0x040400
acceptNavigationRequest(QWebFrame * frame,const QWebNetworkRequest & request,QWebPage::NavigationType type)349 bool QWebPagePrivate::acceptNavigationRequest(QWebFrame *frame, const QWebNetworkRequest &request, QWebPage::NavigationType type)
350 {
351     if (insideOpenCall
352         && frame == mainFrame)
353         return true;
354     return q->acceptNavigationRequest(frame, request, type);
355 }
356 #else
acceptNavigationRequest(QWebFrame * frame,const QNetworkRequest & request,QWebPage::NavigationType type)357 bool QWebPagePrivate::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
358 {
359     if (insideOpenCall
360         && frame == mainFrame)
361         return true;
362     return q->acceptNavigationRequest(frame, request, type);
363 }
364 #endif
365 
createMainFrame()366 void QWebPagePrivate::createMainFrame()
367 {
368     if (!mainFrame) {
369         QWebFrameData frameData(page);
370         mainFrame = new QWebFrame(q, &frameData);
371 
372         emit q->frameCreated(mainFrame);
373     }
374 }
375 
webActionForContextMenuAction(WebCore::ContextMenuAction action)376 static QWebPage::WebAction webActionForContextMenuAction(WebCore::ContextMenuAction action)
377 {
378     switch (action) {
379         case WebCore::ContextMenuItemTagOpenLink: return QWebPage::OpenLink;
380         case WebCore::ContextMenuItemTagOpenLinkInNewWindow: return QWebPage::OpenLinkInNewWindow;
381         case WebCore::ContextMenuItemTagDownloadLinkToDisk: return QWebPage::DownloadLinkToDisk;
382         case WebCore::ContextMenuItemTagCopyLinkToClipboard: return QWebPage::CopyLinkToClipboard;
383         case WebCore::ContextMenuItemTagOpenImageInNewWindow: return QWebPage::OpenImageInNewWindow;
384         case WebCore::ContextMenuItemTagDownloadImageToDisk: return QWebPage::DownloadImageToDisk;
385         case WebCore::ContextMenuItemTagCopyImageToClipboard: return QWebPage::CopyImageToClipboard;
386         case WebCore::ContextMenuItemTagOpenFrameInNewWindow: return QWebPage::OpenFrameInNewWindow;
387         case WebCore::ContextMenuItemTagCopy: return QWebPage::Copy;
388         case WebCore::ContextMenuItemTagGoBack: return QWebPage::Back;
389         case WebCore::ContextMenuItemTagGoForward: return QWebPage::Forward;
390         case WebCore::ContextMenuItemTagStop: return QWebPage::Stop;
391         case WebCore::ContextMenuItemTagReload: return QWebPage::Reload;
392         case WebCore::ContextMenuItemTagCut: return QWebPage::Cut;
393         case WebCore::ContextMenuItemTagPaste: return QWebPage::Paste;
394         case WebCore::ContextMenuItemTagDefaultDirection: return QWebPage::SetTextDirectionDefault;
395         case WebCore::ContextMenuItemTagLeftToRight: return QWebPage::SetTextDirectionLeftToRight;
396         case WebCore::ContextMenuItemTagRightToLeft: return QWebPage::SetTextDirectionRightToLeft;
397         case WebCore::ContextMenuItemTagBold: return QWebPage::ToggleBold;
398         case WebCore::ContextMenuItemTagItalic: return QWebPage::ToggleItalic;
399         case WebCore::ContextMenuItemTagUnderline: return QWebPage::ToggleUnderline;
400         case WebCore::ContextMenuItemTagInspectElement: return QWebPage::InspectElement;
401         default: break;
402     }
403     return QWebPage::NoWebAction;
404 }
405 
406 #ifndef QT_NO_CONTEXTMENU
createContextMenu(const WebCore::ContextMenu * webcoreMenu,const QList<WebCore::ContextMenuItem> * items,QBitArray * visitedWebActions)407 QMenu *QWebPagePrivate::createContextMenu(const WebCore::ContextMenu *webcoreMenu,
408         const QList<WebCore::ContextMenuItem> *items, QBitArray *visitedWebActions)
409 {
410     QMenu* menu = new QMenu(view);
411     for (int i = 0; i < items->count(); ++i) {
412         const ContextMenuItem &item = items->at(i);
413         switch (item.type()) {
414             case WebCore::CheckableActionType: /* fall through */
415             case WebCore::ActionType: {
416                 QWebPage::WebAction action = webActionForContextMenuAction(item.action());
417                 QAction *a = q->action(action);
418                 if (a) {
419                     ContextMenuItem it(item);
420                     webcoreMenu->checkOrEnableIfNeeded(it);
421                     PlatformMenuItemDescription desc = it.releasePlatformDescription();
422                     a->setEnabled(desc.enabled);
423                     a->setChecked(desc.checked);
424                     a->setCheckable(item.type() == WebCore::CheckableActionType);
425 
426                     menu->addAction(a);
427                     visitedWebActions->setBit(action);
428                 }
429                 break;
430             }
431             case WebCore::SeparatorType:
432                 menu->addSeparator();
433                 break;
434             case WebCore::SubmenuType: {
435                 QMenu *subMenu = createContextMenu(webcoreMenu, item.platformSubMenu(), visitedWebActions);
436 
437                 bool anyEnabledAction = false;
438 
439                 QList<QAction *> actions = subMenu->actions();
440                 for (int i = 0; i < actions.count(); ++i) {
441                     if (actions.at(i)->isVisible())
442                         anyEnabledAction |= actions.at(i)->isEnabled();
443                 }
444 
445                 // don't show sub-menus with just disabled actions
446                 if (anyEnabledAction) {
447                     subMenu->setTitle(item.title());
448                     menu->addAction(subMenu->menuAction());
449                 } else
450                     delete subMenu;
451                 break;
452             }
453         }
454     }
455     return menu;
456 }
457 #endif // QT_NO_CONTEXTMENU
458 
_q_webActionTriggered(bool checked)459 void QWebPagePrivate::_q_webActionTriggered(bool checked)
460 {
461     QAction *a = qobject_cast<QAction *>(q->sender());
462     if (!a)
463         return;
464     QWebPage::WebAction action = static_cast<QWebPage::WebAction>(a->data().toInt());
465     q->triggerAction(action, checked);
466 }
467 
468 #ifndef NDEBUG
_q_cleanupLeakMessages()469 void QWebPagePrivate::_q_cleanupLeakMessages()
470 {
471     // Need this to make leak messages accurate.
472     cache()->setCapacities(0, 0, 0);
473 }
474 #endif
475 
updateAction(QWebPage::WebAction action)476 void QWebPagePrivate::updateAction(QWebPage::WebAction action)
477 {
478     QAction *a = actions[action];
479     if (!a || !mainFrame)
480         return;
481 
482     WebCore::FrameLoader *loader = mainFrame->d->frame->loader();
483     WebCore::Editor *editor = page->focusController()->focusedOrMainFrame()->editor();
484 
485     bool enabled = a->isEnabled();
486     bool checked = a->isChecked();
487 
488     switch (action) {
489         case QWebPage::Back:
490             enabled = loader->canGoBackOrForward(-1);
491             break;
492         case QWebPage::Forward:
493             enabled = loader->canGoBackOrForward(1);
494             break;
495         case QWebPage::Stop:
496             enabled = loader->isLoading();
497             break;
498         case QWebPage::Reload:
499         case QWebPage::ReloadAndBypassCache:
500             enabled = !loader->isLoading();
501             break;
502 #ifndef QT_NO_UNDOSTACK
503         case QWebPage::Undo:
504         case QWebPage::Redo:
505             // those two are handled by QUndoStack
506             break;
507 #endif // QT_NO_UNDOSTACK
508         case QWebPage::SelectAll: // editor command is always enabled
509             break;
510         case QWebPage::SetTextDirectionDefault:
511         case QWebPage::SetTextDirectionLeftToRight:
512         case QWebPage::SetTextDirectionRightToLeft:
513             enabled = editor->canEdit();
514             checked = false;
515             break;
516         default: {
517             // see if it's an editor command
518             const char* commandName = editorCommandForWebActions(action);
519 
520             // if it's an editor command, let it's logic determine state
521             if (commandName) {
522                 Editor::Command command = editor->command(commandName);
523                 enabled = command.isEnabled();
524                 if (enabled)
525                     checked = command.state() != FalseTriState;
526                 else
527                     checked = false;
528             }
529             break;
530         }
531     }
532 
533     a->setEnabled(enabled);
534 
535     if (a->isCheckable())
536         a->setChecked(checked);
537 }
538 
updateNavigationActions()539 void QWebPagePrivate::updateNavigationActions()
540 {
541     updateAction(QWebPage::Back);
542     updateAction(QWebPage::Forward);
543     updateAction(QWebPage::Stop);
544     updateAction(QWebPage::Reload);
545     updateAction(QWebPage::ReloadAndBypassCache);
546 }
547 
updateEditorActions()548 void QWebPagePrivate::updateEditorActions()
549 {
550     updateAction(QWebPage::Cut);
551     updateAction(QWebPage::Copy);
552     updateAction(QWebPage::Paste);
553     updateAction(QWebPage::MoveToNextChar);
554     updateAction(QWebPage::MoveToPreviousChar);
555     updateAction(QWebPage::MoveToNextWord);
556     updateAction(QWebPage::MoveToPreviousWord);
557     updateAction(QWebPage::MoveToNextLine);
558     updateAction(QWebPage::MoveToPreviousLine);
559     updateAction(QWebPage::MoveToStartOfLine);
560     updateAction(QWebPage::MoveToEndOfLine);
561     updateAction(QWebPage::MoveToStartOfBlock);
562     updateAction(QWebPage::MoveToEndOfBlock);
563     updateAction(QWebPage::MoveToStartOfDocument);
564     updateAction(QWebPage::MoveToEndOfDocument);
565     updateAction(QWebPage::SelectNextChar);
566     updateAction(QWebPage::SelectPreviousChar);
567     updateAction(QWebPage::SelectNextWord);
568     updateAction(QWebPage::SelectPreviousWord);
569     updateAction(QWebPage::SelectNextLine);
570     updateAction(QWebPage::SelectPreviousLine);
571     updateAction(QWebPage::SelectStartOfLine);
572     updateAction(QWebPage::SelectEndOfLine);
573     updateAction(QWebPage::SelectStartOfBlock);
574     updateAction(QWebPage::SelectEndOfBlock);
575     updateAction(QWebPage::SelectStartOfDocument);
576     updateAction(QWebPage::SelectEndOfDocument);
577     updateAction(QWebPage::DeleteStartOfWord);
578     updateAction(QWebPage::DeleteEndOfWord);
579     updateAction(QWebPage::SetTextDirectionDefault);
580     updateAction(QWebPage::SetTextDirectionLeftToRight);
581     updateAction(QWebPage::SetTextDirectionRightToLeft);
582     updateAction(QWebPage::ToggleBold);
583     updateAction(QWebPage::ToggleItalic);
584     updateAction(QWebPage::ToggleUnderline);
585     updateAction(QWebPage::InsertParagraphSeparator);
586     updateAction(QWebPage::InsertLineSeparator);
587     updateAction(QWebPage::PasteAndMatchStyle);
588     updateAction(QWebPage::RemoveFormat);
589     updateAction(QWebPage::ToggleStrikethrough);
590     updateAction(QWebPage::ToggleSubscript);
591     updateAction(QWebPage::ToggleSuperscript);
592     updateAction(QWebPage::InsertUnorderedList);
593     updateAction(QWebPage::InsertOrderedList);
594     updateAction(QWebPage::Indent);
595     updateAction(QWebPage::Outdent);
596     updateAction(QWebPage::AlignCenter);
597     updateAction(QWebPage::AlignJustified);
598     updateAction(QWebPage::AlignLeft);
599     updateAction(QWebPage::AlignRight);
600 }
601 
timerEvent(QTimerEvent * ev)602 void QWebPagePrivate::timerEvent(QTimerEvent *ev)
603 {
604     int timerId = ev->timerId();
605     if (timerId == tripleClickTimer.timerId())
606         tripleClickTimer.stop();
607     else
608         q->QObject::timerEvent(ev);
609 }
610 
mouseMoveEvent(QMouseEvent * ev)611 void QWebPagePrivate::mouseMoveEvent(QMouseEvent *ev)
612 {
613     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
614     if (!frame->view())
615         return;
616 
617     bool accepted = frame->eventHandler()->mouseMoved(PlatformMouseEvent(ev, 0));
618     ev->setAccepted(accepted);
619 }
620 
mousePressEvent(QMouseEvent * ev)621 void QWebPagePrivate::mousePressEvent(QMouseEvent *ev)
622 {
623     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
624     if (!frame->view())
625         return;
626 
627     if (tripleClickTimer.isActive()
628             && (ev->pos() - tripleClick).manhattanLength()
629                 < QApplication::startDragDistance()) {
630         mouseTripleClickEvent(ev);
631         return;
632     }
633 
634     bool accepted = false;
635     PlatformMouseEvent mev(ev, 1);
636     // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
637     if (mev.button() != NoButton)
638         accepted = frame->eventHandler()->handleMousePressEvent(mev);
639     ev->setAccepted(accepted);
640 }
641 
mouseDoubleClickEvent(QMouseEvent * ev)642 void QWebPagePrivate::mouseDoubleClickEvent(QMouseEvent *ev)
643 {
644     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
645     if (!frame->view())
646         return;
647 
648     bool accepted = false;
649     PlatformMouseEvent mev(ev, 2);
650     // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
651     if (mev.button() != NoButton)
652         accepted = frame->eventHandler()->handleMousePressEvent(mev);
653     ev->setAccepted(accepted);
654 
655     tripleClickTimer.start(QApplication::doubleClickInterval(), q);
656     tripleClick = ev->pos();
657 }
658 
mouseTripleClickEvent(QMouseEvent * ev)659 void QWebPagePrivate::mouseTripleClickEvent(QMouseEvent *ev)
660 {
661     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
662     if (!frame->view())
663         return;
664 
665     bool accepted = false;
666     PlatformMouseEvent mev(ev, 3);
667     // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
668     if (mev.button() != NoButton)
669         accepted = frame->eventHandler()->handleMousePressEvent(mev);
670     ev->setAccepted(accepted);
671 }
672 
mouseReleaseEvent(QMouseEvent * ev)673 void QWebPagePrivate::mouseReleaseEvent(QMouseEvent *ev)
674 {
675     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
676     if (!frame->view())
677         return;
678 
679     bool accepted = false;
680     PlatformMouseEvent mev(ev, 0);
681     // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
682     if (mev.button() != NoButton)
683         accepted = frame->eventHandler()->handleMouseReleaseEvent(mev);
684     ev->setAccepted(accepted);
685 
686 #ifndef QT_NO_CLIPBOARD
687     if (QApplication::clipboard()->supportsSelection()) {
688         bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode();
689         Pasteboard::generalPasteboard()->setSelectionMode(true);
690         WebCore::Frame* focusFrame = page->focusController()->focusedOrMainFrame();
691         if (ev->button() == Qt::LeftButton) {
692             if (focusFrame && (focusFrame->editor()->canCopy() || focusFrame->editor()->canDHTMLCopy())) {
693                 focusFrame->editor()->copy();
694                 ev->setAccepted(true);
695             }
696         } else if (ev->button() == Qt::MidButton) {
697             if (focusFrame && (focusFrame->editor()->canPaste() || focusFrame->editor()->canDHTMLPaste())) {
698                 focusFrame->editor()->paste();
699                 ev->setAccepted(true);
700             }
701         }
702         Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode);
703     }
704 #endif
705 }
706 
707 #ifndef QT_NO_CONTEXTMENU
contextMenuEvent(QContextMenuEvent * ev)708 void QWebPagePrivate::contextMenuEvent(QContextMenuEvent *ev)
709 {
710     QMenu *menu = q->createStandardContextMenu();
711     if (menu) {
712         menu->exec(ev->globalPos());
713         delete menu;
714     }
715 }
716 #endif // QT_NO_CONTEXTMENU
717 
718 /*!
719     \since 4.5
720     This function creates the standard context menu which is shown when
721     the user clicks on the web page with the right mouse button. It is
722     called from the default contextMenuEvent() handler. The popup menu's
723     ownership is transferred to the caller.
724  */
createStandardContextMenu()725 QMenu *QWebPage::createStandardContextMenu()
726 {
727 #ifndef QT_NO_CONTEXTMENU
728     QMenu *menu = d->currentContextMenu;
729     d->currentContextMenu = 0;
730     return menu;
731 #else
732     return 0;
733 #endif
734 }
735 
736 #ifndef QT_NO_WHEELEVENT
wheelEvent(QWheelEvent * ev)737 void QWebPagePrivate::wheelEvent(QWheelEvent *ev)
738 {
739     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
740     if (!frame->view())
741         return;
742 
743     WebCore::PlatformWheelEvent pev(ev);
744     bool accepted = frame->eventHandler()->handleWheelEvent(pev);
745     ev->setAccepted(accepted);
746 }
747 #endif // QT_NO_WHEELEVENT
748 
749 #ifndef QT_NO_SHORTCUT
editorActionForKeyEvent(QKeyEvent * event)750 QWebPage::WebAction QWebPagePrivate::editorActionForKeyEvent(QKeyEvent* event)
751 {
752     static struct {
753         QKeySequence::StandardKey standardKey;
754         QWebPage::WebAction action;
755     } editorActions[] = {
756         { QKeySequence::Cut, QWebPage::Cut },
757         { QKeySequence::Copy, QWebPage::Copy },
758         { QKeySequence::Paste, QWebPage::Paste },
759         { QKeySequence::Undo, QWebPage::Undo },
760         { QKeySequence::Redo, QWebPage::Redo },
761         { QKeySequence::MoveToNextChar, QWebPage::MoveToNextChar },
762         { QKeySequence::MoveToPreviousChar, QWebPage::MoveToPreviousChar },
763         { QKeySequence::MoveToNextWord, QWebPage::MoveToNextWord },
764         { QKeySequence::MoveToPreviousWord, QWebPage::MoveToPreviousWord },
765         { QKeySequence::MoveToNextLine, QWebPage::MoveToNextLine },
766         { QKeySequence::MoveToPreviousLine, QWebPage::MoveToPreviousLine },
767         { QKeySequence::MoveToStartOfLine, QWebPage::MoveToStartOfLine },
768         { QKeySequence::MoveToEndOfLine, QWebPage::MoveToEndOfLine },
769         { QKeySequence::MoveToStartOfBlock, QWebPage::MoveToStartOfBlock },
770         { QKeySequence::MoveToEndOfBlock, QWebPage::MoveToEndOfBlock },
771         { QKeySequence::MoveToStartOfDocument, QWebPage::MoveToStartOfDocument },
772         { QKeySequence::MoveToEndOfDocument, QWebPage::MoveToEndOfDocument },
773         { QKeySequence::SelectNextChar, QWebPage::SelectNextChar },
774         { QKeySequence::SelectPreviousChar, QWebPage::SelectPreviousChar },
775         { QKeySequence::SelectNextWord, QWebPage::SelectNextWord },
776         { QKeySequence::SelectPreviousWord, QWebPage::SelectPreviousWord },
777         { QKeySequence::SelectNextLine, QWebPage::SelectNextLine },
778         { QKeySequence::SelectPreviousLine, QWebPage::SelectPreviousLine },
779         { QKeySequence::SelectStartOfLine, QWebPage::SelectStartOfLine },
780         { QKeySequence::SelectEndOfLine, QWebPage::SelectEndOfLine },
781         { QKeySequence::SelectStartOfBlock, QWebPage::SelectStartOfBlock },
782         { QKeySequence::SelectEndOfBlock,  QWebPage::SelectEndOfBlock },
783         { QKeySequence::SelectStartOfDocument, QWebPage::SelectStartOfDocument },
784         { QKeySequence::SelectEndOfDocument, QWebPage::SelectEndOfDocument },
785         { QKeySequence::DeleteStartOfWord, QWebPage::DeleteStartOfWord },
786         { QKeySequence::DeleteEndOfWord, QWebPage::DeleteEndOfWord },
787 #if QT_VERSION >= 0x040500
788         { QKeySequence::InsertParagraphSeparator, QWebPage::InsertParagraphSeparator },
789         { QKeySequence::InsertLineSeparator, QWebPage::InsertLineSeparator },
790 #endif
791         { QKeySequence::SelectAll, QWebPage::SelectAll },
792         { QKeySequence::UnknownKey, QWebPage::NoWebAction }
793     };
794 
795     for (int i = 0; editorActions[i].standardKey != QKeySequence::UnknownKey; ++i)
796         if (event == editorActions[i].standardKey)
797             return editorActions[i].action;
798 
799     return QWebPage::NoWebAction;
800 }
801 #endif // QT_NO_SHORTCUT
802 
keyPressEvent(QKeyEvent * ev)803 void QWebPagePrivate::keyPressEvent(QKeyEvent *ev)
804 {
805     bool handled = false;
806     WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
807     WebCore::Editor* editor = frame->editor();
808     // we forward the key event to WebCore first to handle potential DOM
809     // defined event handlers and later on end up in EditorClientQt::handleKeyboardEvent
810     // to trigger editor commands via triggerAction().
811     if (!handled)
812         handled = frame->eventHandler()->keyEvent(ev);
813     if (!handled) {
814         handled = true;
815         QFont defaultFont;
816         if (view)
817             defaultFont = view->font();
818         QFontMetrics fm(defaultFont);
819         int fontHeight = fm.height();
820         if (!handleScrolling(ev, frame)) {
821             switch (ev->key()) {
822             case Qt::Key_Back:
823                 q->triggerAction(QWebPage::Back);
824                 break;
825             case Qt::Key_Forward:
826                 q->triggerAction(QWebPage::Forward);
827                 break;
828             case Qt::Key_Stop:
829                 q->triggerAction(QWebPage::Stop);
830                 break;
831             case Qt::Key_Refresh:
832                 q->triggerAction(QWebPage::Reload);
833                 break;
834             case Qt::Key_Backspace:
835                 if (ev->modifiers() == Qt::ShiftModifier)
836                     q->triggerAction(QWebPage::Forward);
837                 else
838                     q->triggerAction(QWebPage::Back);
839                 break;
840             default:
841                 handled = false;
842                 break;
843             }
844         }
845     }
846 
847     ev->setAccepted(handled);
848 }
849 
keyReleaseEvent(QKeyEvent * ev)850 void QWebPagePrivate::keyReleaseEvent(QKeyEvent *ev)
851 {
852     if (ev->isAutoRepeat()) {
853         ev->setAccepted(true);
854         return;
855     }
856 
857     WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
858     bool handled = frame->eventHandler()->keyEvent(ev);
859     ev->setAccepted(handled);
860 }
861 
focusInEvent(QFocusEvent * ev)862 void QWebPagePrivate::focusInEvent(QFocusEvent *ev)
863 {
864     FocusController *focusController = page->focusController();
865     Frame *frame = focusController->focusedFrame();
866     focusController->setActive(true);
867     if (frame)
868         focusController->setFocused(true);
869     else
870         focusController->setFocusedFrame(QWebFramePrivate::core(mainFrame));
871 }
872 
focusOutEvent(QFocusEvent * ev)873 void QWebPagePrivate::focusOutEvent(QFocusEvent *ev)
874 {
875     // only set the focused frame inactive so that we stop painting the caret
876     // and the focus frame. But don't tell the focus controller so that upon
877     // focusInEvent() we can re-activate the frame.
878     FocusController *focusController = page->focusController();
879     focusController->setActive(false);
880     focusController->setFocused(false);
881 }
882 
dragEnterEvent(QDragEnterEvent * ev)883 void QWebPagePrivate::dragEnterEvent(QDragEnterEvent *ev)
884 {
885 #ifndef QT_NO_DRAGANDDROP
886     DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(),
887                       dropActionToDragOp(ev->possibleActions()));
888     Qt::DropAction action = dragOpToDropAction(page->dragController()->dragEntered(&dragData));
889     ev->setDropAction(action);
890     if (action != Qt::IgnoreAction)
891         ev->accept();
892 #endif
893 }
894 
dragLeaveEvent(QDragLeaveEvent * ev)895 void QWebPagePrivate::dragLeaveEvent(QDragLeaveEvent *ev)
896 {
897 #ifndef QT_NO_DRAGANDDROP
898     DragData dragData(0, IntPoint(), QCursor::pos(), DragOperationNone);
899     page->dragController()->dragExited(&dragData);
900     ev->accept();
901 #endif
902 }
903 
dragMoveEvent(QDragMoveEvent * ev)904 void QWebPagePrivate::dragMoveEvent(QDragMoveEvent *ev)
905 {
906 #ifndef QT_NO_DRAGANDDROP
907     DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(),
908                       dropActionToDragOp(ev->possibleActions()));
909     Qt::DropAction action = dragOpToDropAction(page->dragController()->dragUpdated(&dragData));
910     ev->setDropAction(action);
911     if (action != Qt::IgnoreAction)
912         ev->accept();
913 #endif
914 }
915 
dropEvent(QDropEvent * ev)916 void QWebPagePrivate::dropEvent(QDropEvent *ev)
917 {
918 #ifndef QT_NO_DRAGANDDROP
919     DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(),
920                       dropActionToDragOp(ev->possibleActions()));
921     Qt::DropAction action = dragOpToDropAction(page->dragController()->performDrag(&dragData));
922     if (action != Qt::IgnoreAction)
923         ev->accept();
924 #endif
925 }
926 
leaveEvent(QEvent * ev)927 void QWebPagePrivate::leaveEvent(QEvent *ev)
928 {
929     // Fake a mouse move event just outside of the widget, since all
930     // the interesting mouse-out behavior like invalidating scrollbars
931     // is handled by the WebKit event handler's mouseMoved function.
932     QMouseEvent fakeEvent(QEvent::MouseMove, QCursor::pos(), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
933     mouseMoveEvent(&fakeEvent);
934 }
935 
936 /*!
937     \property QWebPage::palette
938     \brief the page's palette
939 
940     The base brush of the palette is used to draw the background of the main frame.
941 
942     By default, this property contains the application's default palette.
943 */
setPalette(const QPalette & pal)944 void QWebPage::setPalette(const QPalette &pal)
945 {
946     d->palette = pal;
947     if (!d->mainFrame || !d->mainFrame->d->frame->view())
948         return;
949 
950     QBrush brush = pal.brush(QPalette::Base);
951     QColor backgroundColor = brush.style() == Qt::SolidPattern ? brush.color() : QColor();
952     QWebFramePrivate::core(d->mainFrame)->view()->updateBackgroundRecursively(backgroundColor, !backgroundColor.alpha());
953 }
954 
palette() const955 QPalette QWebPage::palette() const
956 {
957     return d->palette;
958 }
959 
inputMethodEvent(QInputMethodEvent * ev)960 void QWebPagePrivate::inputMethodEvent(QInputMethodEvent *ev)
961 {
962     WebCore::Frame *frame = page->focusController()->focusedOrMainFrame();
963     WebCore::Editor *editor = frame->editor();
964 
965     if (!editor->canEdit()) {
966         ev->ignore();
967         return;
968     }
969 
970     if (!ev->commitString().isEmpty())
971         editor->confirmComposition(ev->commitString());
972     else {
973         QString preedit = ev->preeditString();
974         // ### FIXME: use the provided QTextCharFormat (use color at least)
975         Vector<CompositionUnderline> underlines;
976         underlines.append(CompositionUnderline(0, preedit.length(), Color(0, 0, 0), false));
977         editor->setComposition(preedit, underlines, preedit.length(), 0);
978     }
979     ev->accept();
980 }
981 
shortcutOverrideEvent(QKeyEvent * event)982 void QWebPagePrivate::shortcutOverrideEvent(QKeyEvent* event)
983 {
984     WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
985     WebCore::Editor* editor = frame->editor();
986     if (editor->canEdit()) {
987         if (event->modifiers() == Qt::NoModifier
988             || event->modifiers() == Qt::ShiftModifier
989             || event->modifiers() == Qt::KeypadModifier) {
990                 if (event->key() < Qt::Key_Escape) {
991                     event->accept();
992                 } else {
993                     switch (event->key()) {
994                     case Qt::Key_Return:
995                     case Qt::Key_Enter:
996                     case Qt::Key_Delete:
997                     case Qt::Key_Home:
998                     case Qt::Key_End:
999                     case Qt::Key_Backspace:
1000                     case Qt::Key_Left:
1001                     case Qt::Key_Right:
1002                     case Qt::Key_Up:
1003                     case Qt::Key_Down:
1004                     case Qt::Key_Tab:
1005                         event->accept();
1006                     default:
1007                         break;
1008                     }
1009                 }
1010         }
1011 #ifndef QT_NO_SHORTCUT
1012         else if (editorActionForKeyEvent(event) != QWebPage::NoWebAction)
1013             event->accept();
1014 #endif
1015     }
1016 }
1017 
handleScrolling(QKeyEvent * ev,Frame * frame)1018 bool QWebPagePrivate::handleScrolling(QKeyEvent *ev, Frame *frame)
1019 {
1020     ScrollDirection direction;
1021     ScrollGranularity granularity;
1022 
1023 #ifndef QT_NO_SHORTCUT
1024     if (ev == QKeySequence::MoveToNextPage
1025         || (ev->key() == Qt::Key_Space && !(ev->modifiers() & Qt::ShiftModifier))) {
1026         granularity = ScrollByPage;
1027         direction = ScrollDown;
1028     } else if (ev == QKeySequence::MoveToPreviousPage
1029                || (ev->key() == Qt::Key_Space) && (ev->modifiers() & Qt::ShiftModifier)) {
1030         granularity = ScrollByPage;
1031         direction = ScrollUp;
1032     } else
1033 #endif // QT_NO_SHORTCUT
1034     if (ev->key() == Qt::Key_Up && ev->modifiers() & Qt::ControlModifier
1035                || ev->key() == Qt::Key_Home) {
1036         granularity = ScrollByDocument;
1037         direction = ScrollUp;
1038     } else if (ev->key() == Qt::Key_Down && ev->modifiers() & Qt::ControlModifier
1039                || ev->key() == Qt::Key_End) {
1040         granularity = ScrollByDocument;
1041         direction = ScrollDown;
1042     } else {
1043         switch (ev->key()) {
1044             case Qt::Key_Up:
1045                 granularity = ScrollByLine;
1046                 direction = ScrollUp;
1047                 break;
1048             case Qt::Key_Down:
1049                 granularity = ScrollByLine;
1050                 direction = ScrollDown;
1051                 break;
1052             case Qt::Key_Left:
1053                 granularity = ScrollByLine;
1054                 direction = ScrollLeft;
1055                 break;
1056             case Qt::Key_Right:
1057                 granularity = ScrollByLine;
1058                 direction = ScrollRight;
1059                 break;
1060             default:
1061                 return false;
1062         }
1063     }
1064 
1065     return frame->eventHandler()->scrollRecursively(direction, granularity);
1066 }
1067 
1068 /*!
1069   This method is used by the input method to query a set of properties of the page
1070   to be able to support complex input method operations as support for surrounding
1071   text and reconversions.
1072 
1073   \a property specifies which property is queried.
1074 
1075   \sa QWidget::inputMethodEvent(), QInputMethodEvent, QInputContext
1076 */
inputMethodQuery(Qt::InputMethodQuery property) const1077 QVariant QWebPage::inputMethodQuery(Qt::InputMethodQuery property) const
1078 {
1079     switch (property) {
1080     case Qt::ImMicroFocus: {
1081         Frame *frame = d->page->focusController()->focusedFrame();
1082         if (frame)
1083             return QVariant(frame->selection()->absoluteCaretBounds());
1084         return QVariant();
1085     }
1086     case Qt::ImFont: {
1087         QWebView *webView = qobject_cast<QWebView *>(d->view);
1088         if (webView)
1089             return QVariant(webView->font());
1090         return QVariant();
1091     }
1092     case Qt::ImCursorPosition: {
1093         Frame *frame = d->page->focusController()->focusedFrame();
1094         if (frame) {
1095             VisibleSelection selection = frame->selection()->selection();
1096             if (selection.isCaret())
1097                 return QVariant(selection.start().deprecatedEditingOffset());
1098         }
1099         return QVariant();
1100     }
1101     case Qt::ImSurroundingText: {
1102         Frame *frame = d->page->focusController()->focusedFrame();
1103         if (frame) {
1104             Document *document = frame->document();
1105             if (document->focusedNode())
1106                 return QVariant(document->focusedNode()->nodeValue());
1107         }
1108         return QVariant();
1109     }
1110     case Qt::ImCurrentSelection:
1111         return QVariant(selectedText());
1112     default:
1113         return QVariant();
1114     }
1115 }
1116 
1117 /*!
1118    \enum QWebPage::FindFlag
1119 
1120    This enum describes the options available to QWebPage's findText() function. The options
1121    can be OR-ed together from the following list:
1122 
1123    \value FindBackward Searches backwards instead of forwards.
1124    \value FindCaseSensitively By default findText() works case insensitive. Specifying this option
1125    changes the behaviour to a case sensitive find operation.
1126    \value FindWrapsAroundDocument Makes findText() restart from the beginning of the document if the end
1127    was reached and the text was not found.
1128    \value HighlightAllOccurrences Highlights all existing occurrences of a specific string.
1129 */
1130 
1131 /*!
1132     \enum QWebPage::LinkDelegationPolicy
1133 
1134     This enum defines the delegation policies a webpage can have when activating links and emitting
1135     the linkClicked() signal.
1136 
1137     \value DontDelegateLinks No links are delegated. Instead, QWebPage tries to handle them all.
1138     \value DelegateExternalLinks When activating links that point to documents not stored on the
1139     local filesystem or an equivalent - such as the Qt resource system - then linkClicked() is emitted.
1140     \value DelegateAllLinks Whenever a link is activated the linkClicked() signal is emitted.
1141 */
1142 
1143 /*!
1144     \enum QWebPage::NavigationType
1145 
1146     This enum describes the types of navigation available when browsing through hyperlinked
1147     documents.
1148 
1149     \value NavigationTypeLinkClicked The user clicked on a link or pressed return on a focused link.
1150     \value NavigationTypeFormSubmitted The user activated a submit button for an HTML form.
1151     \value NavigationTypeBackOrForward Navigation to a previously shown document in the back or forward history is requested.
1152     \value NavigationTypeReload The user activated the reload action.
1153     \value NavigationTypeFormResubmitted An HTML form was submitted a second time.
1154     \value NavigationTypeOther A navigation to another document using a method not listed above.
1155 */
1156 
1157 /*!
1158     \enum QWebPage::WebAction
1159 
1160     This enum describes the types of action which can be performed on the web page.
1161 
1162     Actions only have an effect when they are applicable. The availability of
1163     actions can be be determined by checking \l{QAction::}{isEnabled()} on the
1164     action returned by \l{QWebPage::}{action()}.
1165 
1166     One method of enabling the text editing, cursor movement, and text selection actions
1167     is by setting \l contentEditable to true.
1168 
1169     \value NoWebAction No action is triggered.
1170     \value OpenLink Open the current link.
1171     \value OpenLinkInNewWindow Open the current link in a new window.
1172     \value OpenFrameInNewWindow Replicate the current frame in a new window.
1173     \value DownloadLinkToDisk Download the current link to the disk.
1174     \value CopyLinkToClipboard Copy the current link to the clipboard.
1175     \value OpenImageInNewWindow Open the highlighted image in a new window.
1176     \value DownloadImageToDisk Download the highlighted image to the disk.
1177     \value CopyImageToClipboard Copy the highlighted image to the clipboard.
1178     \value Back Navigate back in the history of navigated links.
1179     \value Forward Navigate forward in the history of navigated links.
1180     \value Stop Stop loading the current page.
1181     \value Reload Reload the current page.
1182     \value ReloadAndBypassCache Reload the current page, but do not use any local cache. (Added in Qt 4.6)
1183     \value Cut Cut the content currently selected into the clipboard.
1184     \value Copy Copy the content currently selected into the clipboard.
1185     \value Paste Paste content from the clipboard.
1186     \value Undo Undo the last editing action.
1187     \value Redo Redo the last editing action.
1188     \value MoveToNextChar Move the cursor to the next character.
1189     \value MoveToPreviousChar Move the cursor to the previous character.
1190     \value MoveToNextWord Move the cursor to the next word.
1191     \value MoveToPreviousWord Move the cursor to the previous word.
1192     \value MoveToNextLine Move the cursor to the next line.
1193     \value MoveToPreviousLine Move the cursor to the previous line.
1194     \value MoveToStartOfLine Move the cursor to the start of the line.
1195     \value MoveToEndOfLine Move the cursor to the end of the line.
1196     \value MoveToStartOfBlock Move the cursor to the start of the block.
1197     \value MoveToEndOfBlock Move the cursor to the end of the block.
1198     \value MoveToStartOfDocument Move the cursor to the start of the document.
1199     \value MoveToEndOfDocument Move the cursor to the end of the document.
1200     \value SelectNextChar Select to the next character.
1201     \value SelectPreviousChar Select to the previous character.
1202     \value SelectNextWord Select to the next word.
1203     \value SelectPreviousWord Select to the previous word.
1204     \value SelectNextLine Select to the next line.
1205     \value SelectPreviousLine Select to the previous line.
1206     \value SelectStartOfLine Select to the start of the line.
1207     \value SelectEndOfLine Select to the end of the line.
1208     \value SelectStartOfBlock Select to the start of the block.
1209     \value SelectEndOfBlock Select to the end of the block.
1210     \value SelectStartOfDocument Select to the start of the document.
1211     \value SelectEndOfDocument Select to the end of the document.
1212     \value DeleteStartOfWord Delete to the start of the word.
1213     \value DeleteEndOfWord Delete to the end of the word.
1214     \value SetTextDirectionDefault Set the text direction to the default direction.
1215     \value SetTextDirectionLeftToRight Set the text direction to left-to-right.
1216     \value SetTextDirectionRightToLeft Set the text direction to right-to-left.
1217     \value ToggleBold Toggle the formatting between bold and normal weight.
1218     \value ToggleItalic Toggle the formatting between italic and normal style.
1219     \value ToggleUnderline Toggle underlining.
1220     \value InspectElement Show the Web Inspector with the currently highlighted HTML element.
1221     \value InsertParagraphSeparator Insert a new paragraph.
1222     \value InsertLineSeparator Insert a new line.
1223     \value SelectAll Selects all content.
1224     \value PasteAndMatchStyle Paste content from the clipboard with current style.
1225     \value RemoveFormat Removes formatting and style.
1226     \value ToggleStrikethrough Toggle the formatting between strikethrough and normal style.
1227     \value ToggleSubscript Toggle the formatting between subscript and baseline.
1228     \value ToggleSuperscript Toggle the formatting between supercript and baseline.
1229     \value InsertUnorderedList Toggles the selection between an ordered list and a normal block.
1230     \value InsertOrderedList Toggles the selection between an ordered list and a normal block.
1231     \value Indent Increases the indentation of the currently selected format block by one increment.
1232     \value Outdent Decreases the indentation of the currently selected format block by one increment.
1233     \value AlignCenter Applies center alignment to content.
1234     \value AlignJustified Applies full justification to content.
1235     \value AlignLeft Applies left justification to content.
1236     \value AlignRight Applies right justification to content.
1237 
1238 
1239     \omitvalue WebActionCount
1240 
1241 */
1242 
1243 /*!
1244     \enum QWebPage::WebWindowType
1245 
1246     \value WebBrowserWindow The window is a regular web browser window.
1247     \value WebModalDialog The window acts as modal dialog.
1248 */
1249 
1250 /*!
1251     \class QWebPage
1252     \since 4.4
1253     \brief The QWebPage class provides an object to view and edit web documents.
1254 
1255     QWebPage holds a main frame responsible for web content, settings, the history
1256     of navigated links and actions. This class can be used, together with QWebFrame,
1257     to provide functionality like QWebView in a widget-less environment.
1258 
1259     QWebPage's API is very similar to QWebView, as you are still provided with
1260     common functions like action() (known as \l{QWebView::}{pageAction()} in
1261     QWebView), triggerAction(), findText() and settings(). More QWebView-like
1262     functions can be found in the main frame of QWebPage, obtained via
1263     QWebPage::mainFrame(). For example, the load(), setUrl() and setHtml()
1264     unctions for QWebPage can be accessed using QWebFrame.
1265 
1266     The loadStarted() signal is emitted when the page begins to load.The
1267     loadProgress() signal, on the other hand, is emitted whenever an element
1268     of the web page completes loading, such as an embedded image, a script,
1269     etc. Finally, the loadFinished() signal is emitted when the page has
1270     loaded completely. Its argument, either true or false, indicates whether
1271     or not the load operation succeeded.
1272 
1273     \section1 Using QWebPage in a Widget-less Environment
1274 
1275     Before you begin painting a QWebPage object, you need to set the size of
1276     the viewport by calling setViewportSize(). Then, you invoke the main
1277     frame's render function (QWebFrame::render()). An example of this
1278     is shown in the code snippet below.
1279 
1280     Suppose we have a \c Thumbnail class as follows:
1281 
1282     \snippet webkitsnippets/webpage/main.cpp 0
1283 
1284     The \c Thumbnail's constructor takes in a \a url. We connect our QWebPage
1285     object's \l{QWebPage::}{loadFinished()} signal to our private slot,
1286     \c render().
1287 
1288     \snippet webkitsnippets/webpage/main.cpp 1
1289 
1290     The \c render() function shows how we can paint a thumbnail using a
1291     QWebPage object.
1292 
1293     \snippet webkitsnippets/webpage/main.cpp 2
1294 
1295     We begin by setting the \l{QWebPage::viewportSize()}{viewportSize} and
1296     then we instantiate a QImage object, \c image, with the same size as our
1297     \l{QWebPage::viewportSize()}{viewportSize}. This image is then sent
1298     as a parameter to \c painter. Next, we render the contents of the main
1299     frame and its subframes into \c painter. Finally, we save the scaled image.
1300 
1301     \sa QWebFrame
1302 */
1303 
1304 /*!
1305     Constructs an empty QWebView with parent \a parent.
1306 */
QWebPage(QObject * parent)1307 QWebPage::QWebPage(QObject *parent)
1308     : QObject(parent)
1309     , d(new QWebPagePrivate(this))
1310 {
1311     setView(qobject_cast<QWidget *>(parent));
1312 
1313     connect(this, SIGNAL(loadProgress(int)), this, SLOT(_q_onLoadProgressChanged(int)));
1314 #ifndef NDEBUG
1315     connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(_q_cleanupLeakMessages()));
1316 #endif
1317 }
1318 
1319 /*!
1320     Destroys the web page.
1321 */
~QWebPage()1322 QWebPage::~QWebPage()
1323 {
1324     FrameLoader *loader = d->mainFrame->d->frame->loader();
1325     if (loader)
1326         loader->detachFromParent();
1327     delete d;
1328 }
1329 
1330 /*!
1331     Returns the main frame of the page.
1332 
1333     The main frame provides access to the hierarchy of sub-frames and is also needed if you
1334     want to explicitly render a web page into a given painter.
1335 
1336     \sa currentFrame()
1337 */
mainFrame() const1338 QWebFrame *QWebPage::mainFrame() const
1339 {
1340     d->createMainFrame();
1341     return d->mainFrame;
1342 }
1343 
1344 /*!
1345     Returns the frame currently active.
1346 
1347     \sa mainFrame(), frameCreated()
1348 */
currentFrame() const1349 QWebFrame *QWebPage::currentFrame() const
1350 {
1351     return static_cast<WebCore::FrameLoaderClientQt *>(d->page->focusController()->focusedOrMainFrame()->loader()->client())->webFrame();
1352 }
1353 
1354 
1355 /*!
1356     \since 4.6
1357 
1358     Returns the frame at the given point \a pos.
1359 
1360     \sa mainFrame(), currentFrame()
1361 */
frameAt(const QPoint & pos) const1362 QWebFrame* QWebPage::frameAt(const QPoint& pos) const
1363 {
1364     QWebFrame* webFrame = mainFrame();
1365     if (!webFrame->geometry().contains(pos))
1366         return 0;
1367     QWebHitTestResult hitTestResult = webFrame->hitTestContent(pos);
1368     return hitTestResult.frame();
1369 }
1370 
1371 /*!
1372     Returns a pointer to the view's history of navigated web pages.
1373 */
history() const1374 QWebHistory *QWebPage::history() const
1375 {
1376     return &d->history;
1377 }
1378 
1379 /*!
1380     Sets the \a view that is associated with the web page.
1381 
1382     \sa view()
1383 */
setView(QWidget * view)1384 void QWebPage::setView(QWidget *view)
1385 {
1386     d->view = view;
1387     setViewportSize(view ? view->size() : QSize(0, 0));
1388 }
1389 
1390 /*!
1391     Returns the view widget that is associated with the web page.
1392 
1393     \sa setView()
1394 */
view() const1395 QWidget *QWebPage::view() const
1396 {
1397     return d->view;
1398 }
1399 
1400 /*!
1401     This function is called whenever a JavaScript program tries to print a \a message to the web browser's console.
1402 
1403     For example in case of evaluation errors the source URL may be provided in \a sourceID as well as the \a lineNumber.
1404 
1405     The default implementation prints nothing.
1406 */
javaScriptConsoleMessage(const QString & message,int lineNumber,const QString & sourceID)1407 void QWebPage::javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID)
1408 {
1409     Q_UNUSED(message)
1410     Q_UNUSED(lineNumber)
1411     Q_UNUSED(sourceID)
1412 }
1413 
1414 /*!
1415     This function is called whenever a JavaScript program running inside \a frame calls the alert() function with
1416     the message \a msg.
1417 
1418     The default implementation shows the message, \a msg, with QMessageBox::information.
1419 */
javaScriptAlert(QWebFrame * frame,const QString & msg)1420 void QWebPage::javaScriptAlert(QWebFrame *frame, const QString& msg)
1421 {
1422 #ifndef QT_NO_MESSAGEBOX
1423     QMessageBox::information(d->view, tr("JavaScript Alert - %1").arg(mainFrame()->url().host()), msg, QMessageBox::Ok);
1424 #endif
1425 }
1426 
1427 /*!
1428     This function is called whenever a JavaScript program running inside \a frame calls the confirm() function
1429     with the message, \a msg. Returns true if the user confirms the message; otherwise returns false.
1430 
1431     The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons.
1432 */
javaScriptConfirm(QWebFrame * frame,const QString & msg)1433 bool QWebPage::javaScriptConfirm(QWebFrame *frame, const QString& msg)
1434 {
1435 #ifdef QT_NO_MESSAGEBOX
1436     return true;
1437 #else
1438     return QMessageBox::Yes == QMessageBox::information(d->view, tr("JavaScript Confirm - %1").arg(mainFrame()->url().host()), msg, QMessageBox::Yes, QMessageBox::No);
1439 #endif
1440 }
1441 
1442 /*!
1443     This function is called whenever a JavaScript program running inside \a frame tries to prompt the user for input.
1444     The program may provide an optional message, \a msg, as well as a default value for the input in \a defaultValue.
1445 
1446     If the prompt was cancelled by the user the implementation should return false; otherwise the
1447     result should be written to \a result and true should be returned.
1448 
1449     The default implementation uses QInputDialog::getText.
1450 */
javaScriptPrompt(QWebFrame * frame,const QString & msg,const QString & defaultValue,QString * result)1451 bool QWebPage::javaScriptPrompt(QWebFrame *frame, const QString& msg, const QString& defaultValue, QString* result)
1452 {
1453     bool ok = false;
1454 #ifndef QT_NO_INPUTDIALOG
1455     QString x = QInputDialog::getText(d->view, tr("JavaScript Prompt - %1").arg(mainFrame()->url().host()), msg, QLineEdit::Normal, defaultValue, &ok);
1456     if (ok && result)
1457         *result = x;
1458 #endif
1459     return ok;
1460 }
1461 
1462 /*!
1463     \fn bool QWebPage::shouldInterruptJavaScript()
1464     \since 4.6
1465     This function is called when a JavaScript program is running for a long period of time.
1466 
1467     If the user wanted to stop the JavaScript the implementation should return true; otherwise false.
1468 
1469     The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons.
1470 
1471     \warning Because of binary compatibility constraints, this function is not virtual. If you want to
1472     provide your own implementation in a QWebPage subclass, reimplement the shouldInterruptJavaScript()
1473     slot in your subclass instead. QtWebKit will dynamically detect the slot and call it.
1474 */
shouldInterruptJavaScript()1475 bool QWebPage::shouldInterruptJavaScript()
1476 {
1477 #ifdef QT_NO_MESSAGEBOX
1478     return false;
1479 #else
1480     return QMessageBox::Yes == QMessageBox::information(d->view, 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);
1481 #endif
1482 }
1483 
1484 /*!
1485     This function is called whenever WebKit wants to create a new window of the given \a type, for
1486     example when a JavaScript program requests to open a document in a new window.
1487 
1488     If the new window can be created, the new window's QWebPage is returned; otherwise a null pointer is returned.
1489 
1490     If the view associated with the web page is a QWebView object, then the default implementation forwards
1491     the request to QWebView's createWindow() function; otherwise it returns a null pointer.
1492 
1493     \sa acceptNavigationRequest()
1494 */
createWindow(WebWindowType type)1495 QWebPage *QWebPage::createWindow(WebWindowType type)
1496 {
1497     QWebView *webView = qobject_cast<QWebView *>(d->view);
1498     if (webView) {
1499         QWebView *newView = webView->createWindow(type);
1500         if (newView)
1501             return newView->page();
1502     }
1503     return 0;
1504 }
1505 
1506 /*!
1507     This function is called whenever WebKit encounters a HTML object element with type "application/x-qt-plugin".
1508     The \a classid, \a url, \a paramNames and \a paramValues correspond to the HTML object element attributes and
1509     child elements to configure the embeddable object.
1510 */
createPlugin(const QString & classid,const QUrl & url,const QStringList & paramNames,const QStringList & paramValues)1511 QObject *QWebPage::createPlugin(const QString &classid, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues)
1512 {
1513     Q_UNUSED(classid)
1514     Q_UNUSED(url)
1515     Q_UNUSED(paramNames)
1516     Q_UNUSED(paramValues)
1517     return 0;
1518 }
1519 
frameLoadRequest(const QUrl & url,WebCore::Frame * frame)1520 static WebCore::FrameLoadRequest frameLoadRequest(const QUrl &url, WebCore::Frame *frame)
1521 {
1522     WebCore::ResourceRequest rr(url, frame->loader()->outgoingReferrer());
1523     return WebCore::FrameLoadRequest(rr);
1524 }
1525 
openNewWindow(const QUrl & url,WebCore::Frame * frame)1526 static void openNewWindow(const QUrl& url, WebCore::Frame* frame)
1527 {
1528     if (Page* oldPage = frame->page()) {
1529         WindowFeatures features;
1530         if (Page* newPage = oldPage->chrome()->createWindow(frame,
1531                 frameLoadRequest(url, frame), features))
1532             newPage->chrome()->show();
1533     }
1534 }
1535 
1536 /*!
1537     This function can be called to trigger the specified \a action.
1538     It is also called by QtWebKit if the user triggers the action, for example
1539     through a context menu item.
1540 
1541     If \a action is a checkable action then \a checked specified whether the action
1542     is toggled or not.
1543 
1544     \sa action()
1545 */
triggerAction(WebAction action,bool checked)1546 void QWebPage::triggerAction(WebAction action, bool checked)
1547 {
1548     WebCore::Frame *frame = d->page->focusController()->focusedOrMainFrame();
1549     if (!frame)
1550         return;
1551     WebCore::Editor *editor = frame->editor();
1552     const char *command = 0;
1553 
1554     switch (action) {
1555         case OpenLink:
1556             if (QWebFrame *targetFrame = d->hitTestResult.linkTargetFrame()) {
1557                 WTF::RefPtr<WebCore::Frame> wcFrame = targetFrame->d->frame;
1558                 targetFrame->d->frame->loader()->loadFrameRequest(frameLoadRequest(d->hitTestResult.linkUrl(), wcFrame.get()),
1559                                                                   /*lockHistory*/ false, /*lockBackForwardList*/ false, /*event*/ 0,
1560                                                                   /*FormState*/ 0);
1561                 break;
1562             }
1563             // fall through
1564         case OpenLinkInNewWindow:
1565             openNewWindow(d->hitTestResult.linkUrl(), frame);
1566             break;
1567         case OpenFrameInNewWindow: {
1568             KURL url = frame->loader()->documentLoader()->unreachableURL();
1569             if (url.isEmpty())
1570                 url = frame->loader()->documentLoader()->url();
1571             openNewWindow(url, frame);
1572             break;
1573         }
1574         case CopyLinkToClipboard: {
1575 #if defined(Q_WS_X11)
1576             bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode();
1577             Pasteboard::generalPasteboard()->setSelectionMode(true);
1578             editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText());
1579             Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode);
1580 #endif
1581             editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText());
1582             break;
1583         }
1584         case OpenImageInNewWindow:
1585             openNewWindow(d->hitTestResult.imageUrl(), frame);
1586             break;
1587         case DownloadImageToDisk:
1588             frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.imageUrl(), frame->loader()->outgoingReferrer()));
1589             break;
1590         case DownloadLinkToDisk:
1591             frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.linkUrl(), frame->loader()->outgoingReferrer()));
1592             break;
1593 #ifndef QT_NO_CLIPBOARD
1594         case CopyImageToClipboard:
1595             QApplication::clipboard()->setPixmap(d->hitTestResult.pixmap());
1596             break;
1597 #endif
1598         case Back:
1599             d->page->goBack();
1600             break;
1601         case Forward:
1602             d->page->goForward();
1603             break;
1604         case Stop:
1605             mainFrame()->d->frame->loader()->stopForUserCancel();
1606             break;
1607         case Reload:
1608             mainFrame()->d->frame->loader()->reload(/*endtoendreload*/false);
1609             break;
1610         case ReloadAndBypassCache:
1611             mainFrame()->d->frame->loader()->reload(/*endtoendreload*/true);
1612             break;
1613         case SetTextDirectionDefault:
1614             editor->setBaseWritingDirection(NaturalWritingDirection);
1615             break;
1616         case SetTextDirectionLeftToRight:
1617             editor->setBaseWritingDirection(LeftToRightWritingDirection);
1618             break;
1619         case SetTextDirectionRightToLeft:
1620             editor->setBaseWritingDirection(RightToLeftWritingDirection);
1621             break;
1622         case InspectElement:
1623             if (!d->hitTestResult.isNull())
1624                 d->page->inspectorController()->inspect(d->hitTestResult.d->innerNonSharedNode.get());
1625             else
1626                 d->page->inspectorController()->show();
1627             break;
1628         default:
1629             command = QWebPagePrivate::editorCommandForWebActions(action);
1630             break;
1631     }
1632 
1633     if (command)
1634         editor->command(command).execute();
1635 }
1636 
viewportSize() const1637 QSize QWebPage::viewportSize() const
1638 {
1639     if (d->mainFrame && d->mainFrame->d->frame->view())
1640         return d->mainFrame->d->frame->view()->frameRect().size();
1641 
1642     return d->viewportSize;
1643 }
1644 
1645 /*!
1646     \property QWebPage::viewportSize
1647     \brief the size of the viewport
1648 
1649     The size affects for example the visibility of scrollbars
1650     if the document is larger than the viewport.
1651 
1652     By default, for a newly-created Web page, this property contains a size with
1653     zero width and height.
1654 */
setViewportSize(const QSize & size) const1655 void QWebPage::setViewportSize(const QSize &size) const
1656 {
1657     d->viewportSize = size;
1658 
1659     QWebFrame *frame = mainFrame();
1660     if (frame->d->frame && frame->d->frame->view()) {
1661         WebCore::FrameView* view = frame->d->frame->view();
1662         view->setFrameRect(QRect(QPoint(0, 0), size));
1663         view->forceLayout();
1664         view->adjustViewSize();
1665     }
1666 }
1667 
fixedContentsSize() const1668 QSize QWebPage::fixedContentsSize() const
1669 {
1670     QWebFrame* frame = d->mainFrame;
1671     if (frame) {
1672         WebCore::FrameView* view = frame->d->frame->view();
1673         if (view && view->useFixedLayout())
1674             return d->mainFrame->d->frame->view()->fixedLayoutSize();
1675     }
1676 
1677     return d->fixedLayoutSize;
1678 }
1679 
1680 /*!
1681     \property QWebPage::fixedContentsSize
1682     \since 4.6
1683     \brief the size of the fixed layout
1684 
1685     The size affects the layout of the page in the viewport.  If set to a fixed size of
1686     1024x768 for example then webkit will layout the page as if the viewport were that size
1687     rather than something different.
1688 */
setFixedContentsSize(const QSize & size) const1689 void QWebPage::setFixedContentsSize(const QSize &size) const
1690 {
1691     d->fixedLayoutSize = size;
1692 
1693     QWebFrame *frame = mainFrame();
1694     if (frame->d->frame && frame->d->frame->view()) {
1695         WebCore::FrameView* view = frame->d->frame->view();
1696 
1697         if (size.isValid()) {
1698             view->setUseFixedLayout(true);
1699             view->setFixedLayoutSize(size);
1700             view->forceLayout();
1701         } else if (view->useFixedLayout()) {
1702             view->setUseFixedLayout(false);
1703             view->forceLayout();
1704         }
1705     }
1706 }
1707 
1708 /*!
1709     \fn bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
1710 
1711     This function is called whenever WebKit requests to navigate \a frame to the resource specified by \a request by means of
1712     the specified navigation type \a type.
1713 
1714     If \a frame is a null pointer then navigation to a new window is requested. If the request is
1715     accepted createWindow() will be called.
1716 
1717     The default implementation interprets the page's linkDelegationPolicy and emits linkClicked accordingly or returns true
1718     to let QWebPage handle the navigation itself.
1719 
1720     \sa createWindow()
1721 */
1722 #if QT_VERSION >= 0x040400
acceptNavigationRequest(QWebFrame * frame,const QNetworkRequest & request,QWebPage::NavigationType type)1723 bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
1724 #else
1725 bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QWebNetworkRequest &request, QWebPage::NavigationType type)
1726 #endif
1727 {
1728     if (type == NavigationTypeLinkClicked) {
1729         switch (d->linkPolicy) {
1730             case DontDelegateLinks:
1731                 return true;
1732 
1733             case DelegateExternalLinks:
1734                 if (WebCore::SecurityOrigin::shouldTreatURLSchemeAsLocal(request.url().scheme()))
1735                     return true;
1736                 emit linkClicked(request.url());
1737                 return false;
1738 
1739             case DelegateAllLinks:
1740                 emit linkClicked(request.url());
1741                 return false;
1742         }
1743     }
1744     return true;
1745 }
1746 
1747 /*!
1748     \property QWebPage::selectedText
1749     \brief the text currently selected
1750 
1751     By default, this property contains an empty string.
1752 
1753     \sa selectionChanged()
1754 */
selectedText() const1755 QString QWebPage::selectedText() const
1756 {
1757     return d->page->focusController()->focusedOrMainFrame()->selectedText();
1758 }
1759 
1760 /*!
1761    Returns a QAction for the specified WebAction \a action.
1762 
1763    The action is owned by the QWebPage but you can customize the look by
1764    changing its properties.
1765 
1766    QWebPage also takes care of implementing the action, so that upon
1767    triggering the corresponding action is performed on the page.
1768 
1769    \sa triggerAction()
1770 */
action(WebAction action) const1771 QAction *QWebPage::action(WebAction action) const
1772 {
1773     if (action == QWebPage::NoWebAction) return 0;
1774     if (d->actions[action])
1775         return d->actions[action];
1776 
1777     QString text;
1778     QIcon icon;
1779     QStyle *style = view() ? view()->style() : qApp->style();
1780     bool checkable = false;
1781 
1782     switch (action) {
1783         case OpenLink:
1784             text = contextMenuItemTagOpenLink();
1785             break;
1786         case OpenLinkInNewWindow:
1787             text = contextMenuItemTagOpenLinkInNewWindow();
1788             break;
1789         case OpenFrameInNewWindow:
1790             text = contextMenuItemTagOpenFrameInNewWindow();
1791             break;
1792 
1793         case DownloadLinkToDisk:
1794             text = contextMenuItemTagDownloadLinkToDisk();
1795             break;
1796         case CopyLinkToClipboard:
1797             text = contextMenuItemTagCopyLinkToClipboard();
1798             break;
1799 
1800         case OpenImageInNewWindow:
1801             text = contextMenuItemTagOpenImageInNewWindow();
1802             break;
1803         case DownloadImageToDisk:
1804             text = contextMenuItemTagDownloadImageToDisk();
1805             break;
1806         case CopyImageToClipboard:
1807             text = contextMenuItemTagCopyImageToClipboard();
1808             break;
1809 
1810         case Back:
1811             text = contextMenuItemTagGoBack();
1812 #if QT_VERSION >= 0x040400
1813             icon = style->standardIcon(QStyle::SP_ArrowBack);
1814 #endif
1815             break;
1816         case Forward:
1817             text = contextMenuItemTagGoForward();
1818 #if QT_VERSION >= 0x040400
1819             icon = style->standardIcon(QStyle::SP_ArrowForward);
1820 #endif
1821             break;
1822         case Stop:
1823             text = contextMenuItemTagStop();
1824 #if QT_VERSION >= 0x040400
1825             icon = style->standardIcon(QStyle::SP_BrowserStop);
1826 #endif
1827             break;
1828         case Reload:
1829             text = contextMenuItemTagReload();
1830 #if QT_VERSION >= 0x040400
1831             icon = style->standardIcon(QStyle::SP_BrowserReload);
1832 #endif
1833             break;
1834 
1835         case Cut:
1836             text = contextMenuItemTagCut();
1837             break;
1838         case Copy:
1839             text = contextMenuItemTagCopy();
1840             break;
1841         case Paste:
1842             text = contextMenuItemTagPaste();
1843             break;
1844 #ifndef QT_NO_UNDOSTACK
1845         case Undo: {
1846             QAction *a = undoStack()->createUndoAction(d->q);
1847             d->actions[action] = a;
1848             return a;
1849         }
1850         case Redo: {
1851             QAction *a = undoStack()->createRedoAction(d->q);
1852             d->actions[action] = a;
1853             return a;
1854         }
1855 #endif // QT_NO_UNDOSTACK
1856         case MoveToNextChar:
1857             text = tr("Move the cursor to the next character");
1858             break;
1859         case MoveToPreviousChar:
1860             text = tr("Move the cursor to the previous character");
1861             break;
1862         case MoveToNextWord:
1863             text = tr("Move the cursor to the next word");
1864             break;
1865         case MoveToPreviousWord:
1866             text = tr("Move the cursor to the previous word");
1867             break;
1868         case MoveToNextLine:
1869             text = tr("Move the cursor to the next line");
1870             break;
1871         case MoveToPreviousLine:
1872             text = tr("Move the cursor to the previous line");
1873             break;
1874         case MoveToStartOfLine:
1875             text = tr("Move the cursor to the start of the line");
1876             break;
1877         case MoveToEndOfLine:
1878             text = tr("Move the cursor to the end of the line");
1879             break;
1880         case MoveToStartOfBlock:
1881             text = tr("Move the cursor to the start of the block");
1882             break;
1883         case MoveToEndOfBlock:
1884             text = tr("Move the cursor to the end of the block");
1885             break;
1886         case MoveToStartOfDocument:
1887             text = tr("Move the cursor to the start of the document");
1888             break;
1889         case MoveToEndOfDocument:
1890             text = tr("Move the cursor to the end of the document");
1891             break;
1892         case SelectAll:
1893             text = tr("Select all");
1894             break;
1895         case SelectNextChar:
1896             text = tr("Select to the next character");
1897             break;
1898         case SelectPreviousChar:
1899             text = tr("Select to the previous character");
1900             break;
1901         case SelectNextWord:
1902             text = tr("Select to the next word");
1903             break;
1904         case SelectPreviousWord:
1905             text = tr("Select to the previous word");
1906             break;
1907         case SelectNextLine:
1908             text = tr("Select to the next line");
1909             break;
1910         case SelectPreviousLine:
1911             text = tr("Select to the previous line");
1912             break;
1913         case SelectStartOfLine:
1914             text = tr("Select to the start of the line");
1915             break;
1916         case SelectEndOfLine:
1917             text = tr("Select to the end of the line");
1918             break;
1919         case SelectStartOfBlock:
1920             text = tr("Select to the start of the block");
1921             break;
1922         case SelectEndOfBlock:
1923             text = tr("Select to the end of the block");
1924             break;
1925         case SelectStartOfDocument:
1926             text = tr("Select to the start of the document");
1927             break;
1928         case SelectEndOfDocument:
1929             text = tr("Select to the end of the document");
1930             break;
1931         case DeleteStartOfWord:
1932             text = tr("Delete to the start of the word");
1933             break;
1934         case DeleteEndOfWord:
1935             text = tr("Delete to the end of the word");
1936             break;
1937 
1938         case SetTextDirectionDefault:
1939             text = contextMenuItemTagDefaultDirection();
1940             break;
1941         case SetTextDirectionLeftToRight:
1942             text = contextMenuItemTagLeftToRight();
1943             checkable = true;
1944             break;
1945         case SetTextDirectionRightToLeft:
1946             text = contextMenuItemTagRightToLeft();
1947             checkable = true;
1948             break;
1949 
1950         case ToggleBold:
1951             text = contextMenuItemTagBold();
1952             checkable = true;
1953             break;
1954         case ToggleItalic:
1955             text = contextMenuItemTagItalic();
1956             checkable = true;
1957             break;
1958         case ToggleUnderline:
1959             text = contextMenuItemTagUnderline();
1960             checkable = true;
1961             break;
1962 
1963         case InspectElement:
1964             text = contextMenuItemTagInspectElement();
1965             break;
1966 
1967         case InsertParagraphSeparator:
1968             text = tr("Insert a new paragraph");
1969             break;
1970         case InsertLineSeparator:
1971             text = tr("Insert a new line");
1972             break;
1973 
1974         case PasteAndMatchStyle:
1975             text = tr("Paste and Match Style");
1976             break;
1977         case RemoveFormat:
1978             text = tr("Remove formatting");
1979             break;
1980 
1981         case ToggleStrikethrough:
1982             text = tr("Strikethrough");
1983             checkable = true;
1984             break;
1985         case ToggleSubscript:
1986             text = tr("Subscript");
1987             checkable = true;
1988             break;
1989         case ToggleSuperscript:
1990             text = tr("Superscript");
1991             checkable = true;
1992             break;
1993         case InsertUnorderedList:
1994             text = tr("Insert Bulleted List");
1995             checkable = true;
1996             break;
1997         case InsertOrderedList:
1998             text = tr("Insert Numbered List");
1999             checkable = true;
2000             break;
2001         case Indent:
2002             text = tr("Indent");
2003             break;
2004         case Outdent:
2005             text = tr("Outdent");
2006             break;
2007         case AlignCenter:
2008             text = tr("Center");
2009             break;
2010         case AlignJustified:
2011             text = tr("Justify");
2012             break;
2013         case AlignLeft:
2014             text = tr("Align Left");
2015             break;
2016         case AlignRight:
2017             text = tr("Align Right");
2018             break;
2019 
2020         case NoWebAction:
2021             return 0;
2022     }
2023 
2024     if (text.isEmpty())
2025         return 0;
2026 
2027     QAction *a = new QAction(d->q);
2028     a->setText(text);
2029     a->setData(action);
2030     a->setCheckable(checkable);
2031     a->setIcon(icon);
2032 
2033     connect(a, SIGNAL(triggered(bool)),
2034             this, SLOT(_q_webActionTriggered(bool)));
2035 
2036     d->actions[action] = a;
2037     d->updateAction(action);
2038     return a;
2039 }
2040 
2041 /*!
2042     \property QWebPage::modified
2043     \brief whether the page contains unsubmitted form data
2044 
2045     By default, this property is false.
2046 */
isModified() const2047 bool QWebPage::isModified() const
2048 {
2049 #ifdef QT_NO_UNDOSTACK
2050     return false;
2051 #else
2052     if (!d->undoStack)
2053         return false;
2054     return d->undoStack->canUndo();
2055 #endif // QT_NO_UNDOSTACK
2056 }
2057 
2058 #ifndef QT_NO_UNDOSTACK
2059 /*!
2060     Returns a pointer to the undo stack used for editable content.
2061 */
undoStack() const2062 QUndoStack *QWebPage::undoStack() const
2063 {
2064     if (!d->undoStack)
2065         d->undoStack = new QUndoStack(const_cast<QWebPage *>(this));
2066 
2067     return d->undoStack;
2068 }
2069 #endif // QT_NO_UNDOSTACK
2070 
2071 /*! \reimp
2072 */
event(QEvent * ev)2073 bool QWebPage::event(QEvent *ev)
2074 {
2075     switch (ev->type()) {
2076     case QEvent::Timer:
2077         d->timerEvent(static_cast<QTimerEvent*>(ev));
2078         break;
2079     case QEvent::MouseMove:
2080         d->mouseMoveEvent(static_cast<QMouseEvent*>(ev));
2081         break;
2082     case QEvent::MouseButtonPress:
2083         d->mousePressEvent(static_cast<QMouseEvent*>(ev));
2084         break;
2085     case QEvent::MouseButtonDblClick:
2086         d->mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev));
2087         break;
2088     case QEvent::MouseButtonRelease:
2089         d->mouseReleaseEvent(static_cast<QMouseEvent*>(ev));
2090         break;
2091 #ifndef QT_NO_CONTEXTMENU
2092     case QEvent::ContextMenu:
2093         d->contextMenuEvent(static_cast<QContextMenuEvent*>(ev));
2094         break;
2095 #endif
2096 #ifndef QT_NO_WHEELEVENT
2097     case QEvent::Wheel:
2098         d->wheelEvent(static_cast<QWheelEvent*>(ev));
2099         break;
2100 #endif
2101     case QEvent::KeyPress:
2102         d->keyPressEvent(static_cast<QKeyEvent*>(ev));
2103         break;
2104     case QEvent::KeyRelease:
2105         d->keyReleaseEvent(static_cast<QKeyEvent*>(ev));
2106         break;
2107     case QEvent::FocusIn:
2108         d->focusInEvent(static_cast<QFocusEvent*>(ev));
2109         break;
2110     case QEvent::FocusOut:
2111         d->focusOutEvent(static_cast<QFocusEvent*>(ev));
2112         break;
2113 #ifndef QT_NO_DRAGANDDROP
2114     case QEvent::DragEnter:
2115         d->dragEnterEvent(static_cast<QDragEnterEvent*>(ev));
2116         break;
2117     case QEvent::DragLeave:
2118         d->dragLeaveEvent(static_cast<QDragLeaveEvent*>(ev));
2119         break;
2120     case QEvent::DragMove:
2121         d->dragMoveEvent(static_cast<QDragMoveEvent*>(ev));
2122         break;
2123     case QEvent::Drop:
2124         d->dropEvent(static_cast<QDropEvent*>(ev));
2125         break;
2126 #endif
2127     case QEvent::InputMethod:
2128         d->inputMethodEvent(static_cast<QInputMethodEvent*>(ev));
2129     case QEvent::ShortcutOverride:
2130         d->shortcutOverrideEvent(static_cast<QKeyEvent*>(ev));
2131         break;
2132     case QEvent::Leave:
2133         d->leaveEvent(ev);
2134         break;
2135     default:
2136         return QObject::event(ev);
2137     }
2138 
2139     return true;
2140 }
2141 
2142 /*!
2143     Similar to QWidget::focusNextPrevChild it focuses the next focusable web element
2144     if \a next is true; otherwise the previous element is focused.
2145 
2146     Returns true if it can find a new focusable element, or false if it can't.
2147 */
focusNextPrevChild(bool next)2148 bool QWebPage::focusNextPrevChild(bool next)
2149 {
2150     QKeyEvent ev(QEvent::KeyPress, Qt::Key_Tab, Qt::KeyboardModifiers(next ? Qt::NoModifier : Qt::ShiftModifier));
2151     d->keyPressEvent(&ev);
2152     bool hasFocusedNode = false;
2153     Frame *frame = d->page->focusController()->focusedFrame();
2154     if (frame) {
2155         Document *document = frame->document();
2156         hasFocusedNode = document && document->focusedNode();
2157     }
2158     //qDebug() << "focusNextPrevChild(" << next << ") =" << ev.isAccepted() << "focusedNode?" << hasFocusedNode;
2159     return hasFocusedNode;
2160 }
2161 
2162 /*!
2163     \property QWebPage::contentEditable
2164     \brief whether the content in this QWebPage is editable or not
2165     \since 4.5
2166 
2167     If this property is enabled the contents of the page can be edited by the user through a visible
2168     cursor. If disabled (the default) only HTML elements in the web page with their
2169     \c{contenteditable} attribute set are editable.
2170 */
setContentEditable(bool editable)2171 void QWebPage::setContentEditable(bool editable)
2172 {
2173     if (d->editable != editable) {
2174         d->editable = editable;
2175         d->page->setTabKeyCyclesThroughElements(!editable);
2176         if (d->mainFrame) {
2177             WebCore::Frame* frame = d->mainFrame->d->frame;
2178             if (editable) {
2179                 frame->applyEditingStyleToBodyElement();
2180                 // FIXME: mac port calls this if there is no selectedDOMRange
2181                 //frame->setSelectionFromNone();
2182             } else
2183                 frame->removeEditingStyleFromBodyElement();
2184         }
2185 
2186         d->updateEditorActions();
2187     }
2188 }
2189 
isContentEditable() const2190 bool QWebPage::isContentEditable() const
2191 {
2192     return d->editable;
2193 }
2194 
2195 /*!
2196     \property QWebPage::forwardUnsupportedContent
2197     \brief whether QWebPage should forward unsupported content
2198 
2199     If enabled, the unsupportedContent() signal is emitted with a network reply that
2200     can be used to read the content.
2201 
2202     If disabled, the download of such content is aborted immediately.
2203 
2204     By default unsupported content is not forwarded.
2205 */
2206 
setForwardUnsupportedContent(bool forward)2207 void QWebPage::setForwardUnsupportedContent(bool forward)
2208 {
2209     d->forwardUnsupportedContent = forward;
2210 }
2211 
forwardUnsupportedContent() const2212 bool QWebPage::forwardUnsupportedContent() const
2213 {
2214     return d->forwardUnsupportedContent;
2215 }
2216 
2217 /*!
2218     \property QWebPage::linkDelegationPolicy
2219     \brief how QWebPage should delegate the handling of links through the
2220     linkClicked() signal
2221 
2222     The default is to delegate no links.
2223 */
2224 
setLinkDelegationPolicy(LinkDelegationPolicy policy)2225 void QWebPage::setLinkDelegationPolicy(LinkDelegationPolicy policy)
2226 {
2227     d->linkPolicy = policy;
2228 }
2229 
linkDelegationPolicy() const2230 QWebPage::LinkDelegationPolicy QWebPage::linkDelegationPolicy() const
2231 {
2232     return d->linkPolicy;
2233 }
2234 
2235 #ifndef QT_NO_CONTEXTMENU
2236 /*!
2237     Filters the context menu event, \a event, through handlers for scrollbars and
2238     custom event handlers in the web page. Returns true if the event was handled;
2239     otherwise false.
2240 
2241     A web page may swallow a context menu event through a custom event handler, allowing for context
2242     menus to be implemented in HTML/JavaScript. This is used by \l{http://maps.google.com/}{Google
2243     Maps}, for example.
2244 */
swallowContextMenuEvent(QContextMenuEvent * event)2245 bool QWebPage::swallowContextMenuEvent(QContextMenuEvent *event)
2246 {
2247     d->page->contextMenuController()->clearContextMenu();
2248 
2249     if (QWebFrame* webFrame = frameAt(event->pos())) {
2250         Frame* frame = QWebFramePrivate::core(webFrame);
2251         if (Scrollbar* scrollbar = frame->view()->scrollbarAtPoint(PlatformMouseEvent(event, 1).pos()))
2252             return scrollbar->contextMenu(PlatformMouseEvent(event, 1));
2253     }
2254 
2255     WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame();
2256     focusedFrame->eventHandler()->sendContextMenuEvent(PlatformMouseEvent(event, 1));
2257     ContextMenu *menu = d->page->contextMenuController()->contextMenu();
2258     // If the website defines its own handler then sendContextMenuEvent takes care of
2259     // calling/showing it and the context menu pointer will be zero. This is the case
2260     // on maps.google.com for example.
2261 
2262     return !menu;
2263 }
2264 #endif // QT_NO_CONTEXTMENU
2265 
2266 /*!
2267     Updates the page's actions depending on the position \a pos. For example if \a pos is over an image
2268     element the CopyImageToClipboard action is enabled.
2269 */
updatePositionDependentActions(const QPoint & pos)2270 void QWebPage::updatePositionDependentActions(const QPoint &pos)
2271 {
2272     // First we disable all actions, but keep track of which ones were originally enabled.
2273     QBitArray originallyEnabledWebActions(QWebPage::WebActionCount);
2274     for (int i = ContextMenuItemTagNoAction; i < ContextMenuItemBaseApplicationTag; ++i) {
2275         QWebPage::WebAction action = webActionForContextMenuAction(WebCore::ContextMenuAction(i));
2276         if (QAction *a = this->action(action)) {
2277             originallyEnabledWebActions.setBit(action, a->isEnabled());
2278             a->setEnabled(false);
2279         }
2280     }
2281 
2282     WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame();
2283     HitTestResult result = focusedFrame->eventHandler()->hitTestResultAtPoint(focusedFrame->view()->windowToContents(pos), /*allowShadowContent*/ false);
2284 
2285     if (result.scrollbar())
2286         d->hitTestResult = QWebHitTestResult();
2287     else
2288         d->hitTestResult = QWebHitTestResult(new QWebHitTestResultPrivate(result));
2289     WebCore::ContextMenu menu(result);
2290     menu.populate();
2291     if (d->page->inspectorController()->enabled())
2292         menu.addInspectElementItem();
2293 
2294     QBitArray visitedWebActions(QWebPage::WebActionCount);
2295 
2296 #ifndef QT_NO_CONTEXTMENU
2297     delete d->currentContextMenu;
2298 
2299     // Then we let createContextMenu() enable the actions that are put into the menu
2300     d->currentContextMenu = d->createContextMenu(&menu, menu.platformDescription(), &visitedWebActions);
2301 #endif // QT_NO_CONTEXTMENU
2302 
2303     // Finally, we restore the original enablement for the actions that were not put into the menu.
2304     originallyEnabledWebActions &= ~visitedWebActions; // Mask out visited actions (they're part of the menu)
2305     for (int i = 0; i < QWebPage::WebActionCount; ++i) {
2306         if (originallyEnabledWebActions.at(i)) {
2307             if (QAction *a = this->action(QWebPage::WebAction(i)))
2308                 a->setEnabled(true);
2309         }
2310     }
2311 
2312     // This whole process ensures that any actions put into to the context menu has the right
2313     // enablement, while also keeping the correct enablement for actions that were left out of
2314     // the menu.
2315 
2316 }
2317 
2318 
2319 
2320 /*!
2321     \enum QWebPage::Extension
2322 
2323     This enum describes the types of extensions that the page can support. Before using these extensions, you
2324     should verify that the extension is supported by calling supportsExtension().
2325 
2326     \value ChooseMultipleFilesExtension Whether the web page supports multiple file selection.
2327     This extension is invoked when the web content requests one or more file names, for example
2328     as a result of the user clicking on a "file upload" button in a HTML form where multiple
2329     file selection is allowed.
2330 
2331 */
2332 
2333 /*!
2334     \class QWebPage::ExtensionOption
2335     \since 4.4
2336     \brief The ExtensionOption class provides an extended input argument to QWebPage's extension support.
2337 
2338     \sa QWebPage::extension()
2339 */
2340 
2341 /*!
2342     \class QWebPage::ChooseMultipleFilesExtensionOption
2343     \since 4.5
2344     \brief The ChooseMultipleFilesExtensionOption class describes the option
2345     for the multiple files selection extension.
2346 
2347     The ChooseMultipleFilesExtensionOption class holds the frame originating the request
2348     and the suggested filenames which might be provided.
2349 
2350     \sa QWebPage::chooseFile(), QWebPage::ChooseMultipleFilesExtensionReturn
2351 */
2352 
2353 /*!
2354     \class QWebPage::ChooseMultipleFilesExtensionReturn
2355     \since 4.5
2356     \brief The ChooseMultipleFilesExtensionReturn describes the return value
2357     for the multiple files selection extension.
2358 
2359     The ChooseMultipleFilesExtensionReturn class holds the filenames selected by the user
2360     when the extension is invoked.
2361 
2362     \sa QWebPage::ChooseMultipleFilesExtensionOption
2363 */
2364 
2365 /*!
2366     This virtual function can be reimplemented in a QWebPage subclass to provide support for extensions. The \a option
2367     argument is provided as input to the extension; the output results can be stored in \a output.
2368 
2369     The behavior of this function is determined by \a extension.
2370 
2371     You can call supportsExtension() to check if an extension is supported by the page.
2372 
2373     Returns true if the extension was called successfully; otherwise returns false.
2374 
2375     \sa supportsExtension(), Extension
2376 */
extension(Extension extension,const ExtensionOption * option,ExtensionReturn * output)2377 bool QWebPage::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
2378 {
2379 #ifndef QT_NO_FILEDIALOG
2380     if (extension == ChooseMultipleFilesExtension) {
2381         // FIXME: do not ignore suggestedFiles
2382         QStringList suggestedFiles = static_cast<const ChooseMultipleFilesExtensionOption*>(option)->suggestedFileNames;
2383         QStringList names = QFileDialog::getOpenFileNames(d->view, QString::null);
2384         static_cast<ChooseMultipleFilesExtensionReturn*>(output)->fileNames = names;
2385         return true;
2386     }
2387 #endif
2388 
2389     return false;
2390 }
2391 
2392 /*!
2393     This virtual function returns true if the web page supports \a extension; otherwise false is returned.
2394 
2395     \sa extension()
2396 */
supportsExtension(Extension extension) const2397 bool QWebPage::supportsExtension(Extension extension) const
2398 {
2399 #ifndef QT_NO_FILEDIALOG
2400     return extension == ChooseMultipleFilesExtension;
2401 #else
2402     Q_UNUSED(extension);
2403     return false;
2404 #endif
2405 }
2406 
2407 /*!
2408     Finds the specified string, \a subString, in the page, using the given \a options.
2409 
2410     If the HighlightAllOccurrences flag is passed, the function will highlight all occurrences
2411     that exist in the page. All subsequent calls will extend the highlight, rather than
2412     replace it, with occurrences of the new string.
2413 
2414     If the HighlightAllOccurrences flag is not passed, the function will select an occurrence
2415     and all subsequent calls will replace the current occurrence with the next one.
2416 
2417     To clear the selection, just pass an empty string.
2418 
2419     Returns true if \a subString was found; otherwise returns false.
2420 */
findText(const QString & subString,FindFlags options)2421 bool QWebPage::findText(const QString &subString, FindFlags options)
2422 {
2423     ::TextCaseSensitivity caseSensitivity = ::TextCaseInsensitive;
2424     if (options & FindCaseSensitively)
2425         caseSensitivity = ::TextCaseSensitive;
2426 
2427     if (options & HighlightAllOccurrences) {
2428         if (subString.isEmpty()) {
2429             d->page->unmarkAllTextMatches();
2430             return true;
2431         } else
2432             return d->page->markAllMatchesForText(subString, caseSensitivity, true, 0);
2433     } else {
2434         ::FindDirection direction = ::FindDirectionForward;
2435         if (options & FindBackward)
2436             direction = ::FindDirectionBackward;
2437 
2438         const bool shouldWrap = options & FindWrapsAroundDocument;
2439 
2440         return d->page->findString(subString, caseSensitivity, direction, shouldWrap);
2441     }
2442 }
2443 
2444 /*!
2445     Returns a pointer to the page's settings object.
2446 
2447     \sa QWebSettings::globalSettings()
2448 */
settings() const2449 QWebSettings *QWebPage::settings() const
2450 {
2451     return d->settings;
2452 }
2453 
2454 /*!
2455     This function is called when the web content requests a file name, for example
2456     as a result of the user clicking on a "file upload" button in a HTML form.
2457 
2458     A suggested filename may be provided in \a suggestedFile. The frame originating the
2459     request is provided as \a parentFrame.
2460 */
chooseFile(QWebFrame * parentFrame,const QString & suggestedFile)2461 QString QWebPage::chooseFile(QWebFrame *parentFrame, const QString& suggestedFile)
2462 {
2463 #ifndef QT_NO_FILEDIALOG
2464     return QFileDialog::getOpenFileName(d->view, QString::null, suggestedFile);
2465 #else
2466     return QString::null;
2467 #endif
2468 }
2469 
2470 #if QT_VERSION < 0x040400 && !defined qdoc
2471 
setNetworkInterface(QWebNetworkInterface * interface)2472 void QWebPage::setNetworkInterface(QWebNetworkInterface *interface)
2473 {
2474     d->networkInterface = interface;
2475 }
2476 
networkInterface() const2477 QWebNetworkInterface *QWebPage::networkInterface() const
2478 {
2479     if (d->networkInterface)
2480         return d->networkInterface;
2481     else
2482         return QWebNetworkInterface::defaultInterface();
2483 }
2484 
2485 #ifndef QT_NO_NETWORKPROXY
setNetworkProxy(const QNetworkProxy & proxy)2486 void QWebPage::setNetworkProxy(const QNetworkProxy& proxy)
2487 {
2488     d->networkProxy = proxy;
2489 }
2490 
networkProxy() const2491 QNetworkProxy QWebPage::networkProxy() const
2492 {
2493     return d->networkProxy;
2494 }
2495 #endif
2496 
2497 #else
2498 
2499 /*!
2500     Sets the QNetworkAccessManager \a manager responsible for serving network requests for this
2501     QWebPage.
2502 
2503     \sa networkAccessManager()
2504 */
setNetworkAccessManager(QNetworkAccessManager * manager)2505 void QWebPage::setNetworkAccessManager(QNetworkAccessManager *manager)
2506 {
2507     if (manager == d->networkManager)
2508         return;
2509     if (d->networkManager && d->networkManager->parent() == this)
2510         delete d->networkManager;
2511     d->networkManager = manager;
2512 }
2513 
2514 /*!
2515     Returns the QNetworkAccessManager that is responsible for serving network
2516     requests for this QWebPage.
2517 
2518     \sa setNetworkAccessManager()
2519 */
networkAccessManager() const2520 QNetworkAccessManager *QWebPage::networkAccessManager() const
2521 {
2522     if (!d->networkManager) {
2523         QWebPage *that = const_cast<QWebPage *>(this);
2524         that->d->networkManager = new QNetworkAccessManager(that);
2525     }
2526     return d->networkManager;
2527 }
2528 
2529 #endif
2530 
2531 /*!
2532     Sets the QWebPluginFactory \a factory responsible for creating plugins embedded into this
2533     QWebPage.
2534 
2535     Note: The plugin factory is only used if the QWebSettings::PluginsEnabled attribute is enabled.
2536 
2537     \sa pluginFactory()
2538 */
setPluginFactory(QWebPluginFactory * factory)2539 void QWebPage::setPluginFactory(QWebPluginFactory *factory)
2540 {
2541     d->pluginFactory = factory;
2542 }
2543 
2544 /*!
2545     Returns the QWebPluginFactory that is responsible for creating plugins embedded into
2546     this QWebPage. If no plugin factory is installed a null pointer is returned.
2547 
2548     \sa setPluginFactory()
2549 */
pluginFactory() const2550 QWebPluginFactory *QWebPage::pluginFactory() const
2551 {
2552     return d->pluginFactory;
2553 }
2554 
2555 /*!
2556     This function is called when a user agent for HTTP requests is needed. You can reimplement this
2557     function to dynamically return different user agents for different URLs, based on the \a url parameter.
2558 
2559     The default implementation returns the following value:
2560 
2561     "Mozilla/5.0 (%Platform%; %Security%; %Subplatform%; %Locale%) AppleWebKit/%WebKitVersion% (KHTML, like Gecko) %AppVersion Safari/%WebKitVersion%"
2562 
2563     In this string the following values are replaced at run-time:
2564     \list
2565     \o %Platform% and %Subplatform% are expanded to the windowing system and the operation system.
2566     \o %Security% expands to U if SSL is enabled, otherwise N. SSL is enabled if QSslSocket::supportsSsl() returns true.
2567     \o %Locale% is replaced with QLocale::name(). The locale is determined from the view of the QWebPage. If no view is set on the QWebPage,
2568     then a default constructed QLocale is used instead.
2569     \o %WebKitVersion% is the version of WebKit the application was compiled against.
2570     \o %AppVersion% expands to QCoreApplication::applicationName()/QCoreApplication::applicationVersion() if they're set; otherwise defaulting to Qt and the current Qt version.
2571     \endlist
2572 */
userAgentForUrl(const QUrl & url) const2573 QString QWebPage::userAgentForUrl(const QUrl& url) const
2574 {
2575     Q_UNUSED(url)
2576     QString ua = QLatin1String("Mozilla/5.0 ("
2577 
2578     // Plastform
2579 #ifdef Q_WS_MAC
2580     "Macintosh"
2581 #elif defined Q_WS_QWS
2582     "QtEmbedded"
2583 #elif defined Q_WS_WIN
2584     "Windows"
2585 #elif defined Q_WS_X11
2586     "X11"
2587 #else
2588     "Unknown"
2589 #endif
2590     "; "
2591 
2592     // Placeholder for security strength (N or U)
2593     "%1; "
2594 
2595     // Subplatform"
2596 #ifdef Q_OS_AIX
2597     "AIX"
2598 #elif defined Q_OS_WIN32
2599     "%2"
2600 #elif defined Q_OS_DARWIN
2601 #ifdef __i386__ || __x86_64__
2602     "Intel Mac OS X"
2603 #else
2604     "PPC Mac OS X"
2605 #endif
2606 
2607 #elif defined Q_OS_BSDI
2608     "BSD"
2609 #elif defined Q_OS_BSD4
2610     "BSD Four"
2611 #elif defined Q_OS_CYGWIN
2612     "Cygwin"
2613 #elif defined Q_OS_DGUX
2614     "DG/UX"
2615 #elif defined Q_OS_DYNIX
2616     "DYNIX/ptx"
2617 #elif defined Q_OS_FREEBSD
2618     "FreeBSD"
2619 #elif defined Q_OS_HPUX
2620     "HP-UX"
2621 #elif defined Q_OS_HURD
2622     "GNU Hurd"
2623 #elif defined Q_OS_IRIX
2624     "SGI Irix"
2625 #elif defined Q_OS_LINUX
2626     "Linux"
2627 #elif defined Q_OS_LYNX
2628     "LynxOS"
2629 #elif defined Q_OS_NETBSD
2630     "NetBSD"
2631 #elif defined Q_OS_OS2
2632     "OS/2"
2633 #elif defined Q_OS_OPENBSD
2634     "OpenBSD"
2635 #elif defined Q_OS_OS2EMX
2636     "OS/2"
2637 #elif defined Q_OS_OSF
2638     "HP Tru64 UNIX"
2639 #elif defined Q_OS_QNX6
2640     "QNX RTP Six"
2641 #elif defined Q_OS_QNX
2642     "QNX"
2643 #elif defined Q_OS_RELIANT
2644     "Reliant UNIX"
2645 #elif defined Q_OS_SCO
2646     "SCO OpenServer"
2647 #elif defined Q_OS_SOLARIS
2648     "Sun Solaris"
2649 #elif defined Q_OS_ULTRIX
2650     "DEC Ultrix"
2651 #elif defined Q_OS_UNIX
2652     "UNIX BSD/SYSV system"
2653 #elif defined Q_OS_UNIXWARE
2654     "UnixWare Seven, Open UNIX Eight"
2655 #else
2656     "Unknown"
2657 #endif
2658     "; ");
2659 
2660     QChar securityStrength(QLatin1Char('N'));
2661 #if !defined(QT_NO_OPENSSL)
2662     // we could check QSslSocket::supportsSsl() here, but this makes
2663     // OpenSSL, certificates etc being loaded in all cases were QWebPage
2664     // is used. This loading is not needed for non-https.
2665     securityStrength = QLatin1Char('U');
2666     // this may lead to a false positive: We indicate SSL since it is
2667     // compiled in even though supportsSsl() might return false
2668 #endif
2669     ua = ua.arg(securityStrength);
2670 
2671 #if defined Q_OS_WIN32
2672     QString ver;
2673     switch (QSysInfo::WindowsVersion) {
2674         case QSysInfo::WV_32s:
2675             ver = "Windows 3.1";
2676             break;
2677         case QSysInfo::WV_95:
2678             ver = "Windows 95";
2679             break;
2680         case QSysInfo::WV_98:
2681             ver = "Windows 98";
2682             break;
2683         case QSysInfo::WV_Me:
2684             ver = "Windows 98; Win 9x 4.90";
2685             break;
2686         case QSysInfo::WV_NT:
2687             ver = "WinNT4.0";
2688             break;
2689         case QSysInfo::WV_2000:
2690             ver = "Windows NT 5.0";
2691             break;
2692         case QSysInfo::WV_XP:
2693             ver = "Windows NT 5.1";
2694             break;
2695         case QSysInfo::WV_2003:
2696             ver = "Windows NT 5.2";
2697             break;
2698         case QSysInfo::WV_VISTA:
2699             ver = "Windows NT 6.0";
2700             break;
2701         case QSysInfo::WV_CE:
2702             ver = "Windows CE";
2703             break;
2704         case QSysInfo::WV_CENET:
2705             ver = "Windows CE .NET";
2706             break;
2707         case QSysInfo::WV_CE_5:
2708             ver = "Windows CE 5.x";
2709             break;
2710         case QSysInfo::WV_CE_6:
2711             ver = "Windows CE 6.x";
2712             break;
2713     }
2714     ua = QString(ua).arg(ver);
2715 #endif
2716 
2717     // Language
2718     QLocale locale;
2719     if (d->view)
2720         locale = d->view->locale();
2721     QString name = locale.name();
2722     name[2] = QLatin1Char('-');
2723     ua.append(name);
2724     ua.append(QLatin1String(") "));
2725 
2726     // webkit/qt version
2727     ua.append(QString(QLatin1String("AppleWebKit/%1 (KHTML, like Gecko) "))
2728                       .arg(QString(qWebKitVersion())));
2729 
2730     // Application name/version
2731     QString appName = QCoreApplication::applicationName();
2732     if (!appName.isEmpty()) {
2733         ua.append(appName);
2734 #if QT_VERSION >= 0x040400
2735         QString appVer = QCoreApplication::applicationVersion();
2736         if (!appVer.isEmpty())
2737             ua.append(QLatin1Char('/') + appVer);
2738 #endif
2739     } else {
2740         // Qt version
2741         ua.append(QLatin1String("Qt/"));
2742         ua.append(QLatin1String(qVersion()));
2743     }
2744 
2745     ua.append(QString(QLatin1String(" Safari/%1"))
2746                       .arg(qWebKitVersion()));
2747 
2748     return ua;
2749 }
2750 
2751 
_q_onLoadProgressChanged(int)2752 void QWebPagePrivate::_q_onLoadProgressChanged(int)
2753 {
2754     m_totalBytes = page->progress()->totalPageAndResourceBytesToLoad();
2755     m_bytesReceived = page->progress()->totalBytesReceived();
2756 }
2757 
2758 
2759 /*!
2760     Returns the total number of bytes that were received from the network to render the current page,
2761     including extra content such as embedded images.
2762 
2763     \sa bytesReceived()
2764 */
totalBytes() const2765 quint64 QWebPage::totalBytes() const
2766 {
2767     return d->m_totalBytes;
2768 }
2769 
2770 
2771 /*!
2772     Returns the number of bytes that were received from the network to render the current page.
2773 
2774     \sa totalBytes()
2775 */
bytesReceived() const2776 quint64 QWebPage::bytesReceived() const
2777 {
2778     return d->m_bytesReceived;
2779 }
2780 
2781 /*!
2782     \fn void QWebPage::loadStarted()
2783 
2784     This signal is emitted when a new load of the page is started.
2785 
2786     \sa loadFinished()
2787 */
2788 
2789 /*!
2790     \fn void QWebPage::loadProgress(int progress)
2791 
2792     This signal is emitted when the global progress status changes.
2793     The current value is provided by \a progress and scales from 0 to 100,
2794     which is the default range of QProgressBar.
2795     It accumulates changes from all the child frames.
2796 
2797     \sa bytesReceived()
2798 */
2799 
2800 /*!
2801     \fn void QWebPage::loadFinished(bool ok)
2802 
2803     This signal is emitted when a load of the page is finished.
2804     \a ok will indicate whether the load was successful or any error occurred.
2805 
2806     \sa loadStarted()
2807 */
2808 
2809 /*!
2810     \fn void QWebPage::linkHovered(const QString &link, const QString &title, const QString &textContent)
2811 
2812     This signal is emitted when the mouse hovers over a link.
2813 
2814     \a link contains the link url.
2815     \a title is the link element's title, if it is specified in the markup.
2816     \a textContent provides text within the link element, e.g., text inside an HTML anchor tag.
2817 
2818     When the mouse leaves the link element the signal is emitted with empty parameters.
2819 
2820     \sa linkClicked()
2821 */
2822 
2823 /*!
2824     \fn void QWebPage::statusBarMessage(const QString& text)
2825 
2826     This signal is emitted when the statusbar \a text is changed by the page.
2827 */
2828 
2829 /*!
2830     \fn void QWebPage::frameCreated(QWebFrame *frame)
2831 
2832     This signal is emitted whenever the page creates a new \a frame.
2833 */
2834 
2835 /*!
2836     \fn void QWebPage::selectionChanged()
2837 
2838     This signal is emitted whenever the selection changes.
2839 
2840     \sa selectedText()
2841 */
2842 
2843 /*!
2844     \fn void QWebPage::contentsChanged()
2845     \since 4.5
2846 
2847     This signal is emitted whenever the text in form elements changes
2848     as well as other editable content.
2849 
2850     \sa contentEditable, QWebFrame::toHtml(), QWebFrame::toPlainText()
2851 */
2852 
2853 /*!
2854     \fn void QWebPage::geometryChangeRequested(const QRect& geom)
2855 
2856     This signal is emitted whenever the document wants to change the position and size of the
2857     page to \a geom. This can happen for example through JavaScript.
2858 */
2859 
2860 /*!
2861     \fn void QWebPage::repaintRequested(const QRect& dirtyRect)
2862 
2863     This signal is emitted whenever this QWebPage should be updated and no view was set.
2864     \a dirtyRect contains the area that needs to be updated. To paint the QWebPage get
2865     the mainFrame() and call the render(QPainter*, const QRegion&) method with the
2866     \a dirtyRect as the second parameter.
2867 
2868     \sa mainFrame()
2869     \sa view()
2870 */
2871 
2872 /*!
2873     \fn void QWebPage::scrollRequested(int dx, int dy, const QRect& rectToScroll)
2874 
2875     This signal is emitted whenever the content given by \a rectToScroll needs
2876     to be scrolled \a dx and \a dy downwards and no view was set.
2877 
2878     \sa view()
2879 */
2880 
2881 /*!
2882     \fn void QWebPage::windowCloseRequested()
2883 
2884     This signal is emitted whenever the page requests the web browser window to be closed,
2885     for example through the JavaScript \c{window.close()} call.
2886 */
2887 
2888 /*!
2889     \fn void QWebPage::printRequested(QWebFrame *frame)
2890 
2891     This signal is emitted whenever the page requests the web browser to print \a frame,
2892     for example through the JavaScript \c{window.print()} call.
2893 
2894     \sa QWebFrame::print(), QPrintPreviewDialog
2895 */
2896 
2897 /*!
2898     \fn void QWebPage::unsupportedContent(QNetworkReply *reply)
2899 
2900     This signals is emitted when webkit cannot handle a link the user navigated to.
2901 
2902     At signal emissions time the meta data of the QNetworkReply \a reply is available.
2903 
2904     \note This signal is only emitted if the forwardUnsupportedContent property is set to true.
2905 
2906     \sa downloadRequested()
2907 */
2908 
2909 /*!
2910     \fn void QWebPage::downloadRequested(const QNetworkRequest &request)
2911 
2912     This signal is emitted when the user decides to download a link. The url of
2913     the link as well as additional meta-information is contained in \a request.
2914 
2915     \sa unsupportedContent()
2916 */
2917 
2918 /*!
2919     \fn void QWebPage::microFocusChanged()
2920 
2921     This signal is emitted when for example the position of the cursor in an editable form
2922     element changes. It is used inform input methods about the new on-screen position where
2923     the user is able to enter text. This signal is usually connected to QWidget's updateMicroFocus()
2924     slot.
2925 */
2926 
2927 /*!
2928     \fn void QWebPage::linkClicked(const QUrl &url)
2929 
2930     This signal is emitted whenever the user clicks on a link and the page's linkDelegationPolicy
2931     property is set to delegate the link handling for the specified \a url.
2932 
2933     By default no links are delegated and are handled by QWebPage instead.
2934 
2935     \sa linkHovered()
2936 */
2937 
2938 /*!
2939     \fn void QWebPage::toolBarVisibilityChangeRequested(bool visible)
2940 
2941     This signal is emitted whenever the visibility of the toolbar in a web browser
2942     window that hosts QWebPage should be changed to \a visible.
2943 */
2944 
2945 /*!
2946     \fn void QWebPage::statusBarVisibilityChangeRequested(bool visible)
2947 
2948     This signal is emitted whenever the visibility of the statusbar in a web browser
2949     window that hosts QWebPage should be changed to \a visible.
2950 */
2951 
2952 /*!
2953     \fn void QWebPage::menuBarVisibilityChangeRequested(bool visible)
2954 
2955     This signal is emitted whenever the visibility of the menubar in a web browser
2956     window that hosts QWebPage should be changed to \a visible.
2957 */
2958 
2959 /*!
2960     \fn void QWebPage::databaseQuotaExceeded(QWebFrame* frame, QString databaseName);
2961     \since 4.5
2962 
2963     This signal is emitted whenever the web site shown in \a frame is asking to store data
2964     to the database \a databaseName and the quota allocated to that web site is exceeded.
2965 */
2966 
2967 /*!
2968   \since 4.5
2969   \fn void QWebPage::saveFrameStateRequested(QWebFrame* frame, QWebHistoryItem* item);
2970 
2971   This signal is emitted shortly before the history of navigated pages
2972   in \a frame is changed, for example when navigating back in the history.
2973 
2974   The provided QWebHistoryItem, \a item, holds the history entry of the frame before
2975   the change.
2976 
2977   A potential use-case for this signal is to store custom data in
2978   the QWebHistoryItem associated to the frame, using QWebHistoryItem::setUserData().
2979 */
2980 
2981 /*!
2982   \since 4.5
2983   \fn void QWebPage::restoreFrameStateRequested(QWebFrame* frame);
2984 
2985   This signal is emitted when the load of \a frame is finished and the application may now update its state accordingly.
2986 */
2987 
2988 /*!
2989   \fn QWebPagePrivate* QWebPage::handle() const
2990   \internal
2991 */
2992 
2993 #include "moc_qwebpage.cpp"
2994