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