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