| /* |
| Copyright (C) 2007 Trolltech ASA |
| Copyright (C) 2007 Staikos Computing Services Inc. |
| Copyright (C) 2007 Apple Inc. |
| |
| This library is free software; you can redistribute it and/or |
| modify it under the terms of the GNU Library General Public |
| License as published by the Free Software Foundation; either |
| version 2 of the License, or (at your option) any later version. |
| |
| This library is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| Library General Public License for more details. |
| |
| You should have received a copy of the GNU Library General Public License |
| along with this library; see the file COPYING.LIB. If not, write to |
| the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| Boston, MA 02110-1301, USA. |
| |
| This class provides all functionality needed for loading images, style sheets and html |
| pages from the web. It has a memory cache for these objects. |
| */ |
| |
| #include "qwebpage.h" |
| #include "qwebframe.h" |
| #include "qwebpage_p.h" |
| #include "qwebframe_p.h" |
| #include "qwebnetworkinterface.h" |
| #include "qwebpagehistory.h" |
| #include "qwebpagehistory_p.h" |
| #include "qwebsettings.h" |
| |
| #include "Frame.h" |
| #include "ChromeClientQt.h" |
| #include "ContextMenuClientQt.h" |
| #include "DragClientQt.h" |
| #include "DragController.h" |
| #include "DragData.h" |
| #include "EditorClientQt.h" |
| #include "Settings.h" |
| #include "Page.h" |
| #include "FrameLoader.h" |
| #include "KURL.h" |
| #include "Image.h" |
| #include "IconDatabase.h" |
| #include "InspectorClientQt.h" |
| #include "FocusController.h" |
| #include "Editor.h" |
| #include "PlatformScrollBar.h" |
| #include "PlatformKeyboardEvent.h" |
| #include "ProgressTracker.h" |
| |
| #include <QDebug> |
| #include <QDragEnterEvent> |
| #include <QDragLeaveEvent> |
| #include <QDragMoveEvent> |
| #include <QDropEvent> |
| #include <QFileDialog> |
| #include <QHttpRequestHeader> |
| #include <QInputDialog> |
| #include <QMessageBox> |
| #include <QNetworkProxy> |
| #include <QUndoStack> |
| #include <QUrl> |
| #include <QPainter> |
| |
| using namespace WebCore; |
| |
| QWebPagePrivate::QWebPagePrivate(QWebPage *qq) |
| : q(qq), modified(false) |
| { |
| q->setMouseTracking(true); |
| q->setFocusPolicy(Qt::ClickFocus); |
| chromeClient = new ChromeClientQt(q); |
| contextMenuClient = new ContextMenuClientQt(); |
| editorClient = new EditorClientQt(q); |
| page = new Page(chromeClient, contextMenuClient, editorClient, |
| new DragClientQt(q), new InspectorClientQt()); |
| |
| undoStack = 0; |
| mainFrame = 0; |
| networkInterface = 0; |
| insideOpenCall = false; |
| } |
| |
| QWebPagePrivate::~QWebPagePrivate() |
| { |
| delete undoStack; |
| delete page; |
| } |
| |
| QWebPage::NavigationRequestResponse QWebPagePrivate::navigationRequested(QWebFrame *frame, const QWebNetworkRequest &request, QWebPage::NavigationType type) |
| { |
| if (insideOpenCall |
| && frame == mainFrame) |
| return QWebPage::AcceptNavigationRequest; |
| return q->navigationRequested(frame, request, type); |
| } |
| |
| void QWebPagePrivate::createMainFrame() |
| { |
| if (!mainFrame) { |
| QWebFrameData frameData; |
| frameData.ownerElement = 0; |
| frameData.allowsScrolling = true; |
| frameData.marginWidth = 0; |
| frameData.marginHeight = 0; |
| mainFrame = q->createFrame(0, &frameData); |
| QObject::connect(mainFrame, SIGNAL(titleChanged(const QString&)), |
| q, SIGNAL(titleChanged(const QString&))); |
| QObject::connect(mainFrame, SIGNAL(hoveringOverLink(const QString&, const QString&)), |
| q, SIGNAL(hoveringOverLink(const QString&, const QString&))); |
| |
| mainFrame->d->frameView->setFrameGeometry(q->geometry()); |
| } |
| } |
| |
| |
| QWebPage::QWebPage(QWidget *parent) |
| : QWidget(parent) |
| , d(new QWebPagePrivate(this)) |
| { |
| setSettings(QWebSettings::global()); |
| QPalette pal = palette(); |
| pal.setBrush(QPalette::Background, Qt::white); |
| |
| setAttribute(Qt::WA_OpaquePaintEvent); |
| |
| setPalette(pal); |
| setAcceptDrops(true); |
| connect(this, SIGNAL(loadProgressChanged(int)), this, SLOT(onLoadProgressChanged(int))); |
| } |
| |
| QWebPage::~QWebPage() |
| { |
| FrameLoader *loader = d->mainFrame->d->frame->loader(); |
| if (loader) |
| loader->detachFromParent(); |
| delete d; |
| } |
| |
| QWebFrame *QWebPage::createFrame(QWebFrame *parentFrame, QWebFrameData *frameData) |
| { |
| if (parentFrame) |
| return new QWebFrame(parentFrame, frameData); |
| QWebFrame *f = new QWebFrame(this, frameData); |
| return f; |
| } |
| |
| void QWebPage::open(const QUrl &url) |
| { |
| open(QWebNetworkRequest(url)); |
| } |
| |
| void QWebPage::open(const QWebNetworkRequest &req) |
| { |
| d->insideOpenCall = true; |
| |
| QUrl url = req.url(); |
| QHttpRequestHeader httpHeader = req.httpHeader(); |
| QByteArray postData = req.postData(); |
| |
| WebCore::ResourceRequest request(KURL(url.toString())); |
| |
| QString method = httpHeader.method(); |
| if (!method.isEmpty()) |
| request.setHTTPMethod(method); |
| |
| QList<QPair<QString, QString> > values = httpHeader.values(); |
| for (int i = 0; i < values.size(); ++i) { |
| const QPair<QString, QString> &val = values.at(i); |
| request.addHTTPHeaderField(val.first, val.second); |
| } |
| |
| if (!postData.isEmpty()) { |
| WTF::RefPtr<WebCore::FormData> formData = new WebCore::FormData(postData.constData(), postData.size()); |
| request.setHTTPBody(formData); |
| } |
| |
| mainFrame()->d->frame->loader()->load(request); |
| d->insideOpenCall = false; |
| } |
| |
| QUrl QWebPage::url() const |
| { |
| return QUrl((QString)mainFrame()->d->frame->loader()->url().url()); |
| } |
| |
| QString QWebPage::title() const |
| { |
| return mainFrame()->title(); |
| } |
| |
| QWebFrame *QWebPage::mainFrame() const |
| { |
| d->createMainFrame(); |
| return d->mainFrame; |
| } |
| |
| QSize QWebPage::sizeHint() const |
| { |
| return QSize(800, 600); |
| } |
| |
| void QWebPage::stop() |
| { |
| FrameLoader *f = mainFrame()->d->frame->loader(); |
| f->stopForUserCancel(); |
| } |
| |
| QWebPageHistory QWebPage::history() const |
| { |
| WebCore::BackForwardList *lst = d->page->backForwardList(); |
| QWebPageHistoryPrivate *priv = new QWebPageHistoryPrivate(lst); |
| return QWebPageHistory(priv); |
| } |
| |
| void QWebPage::goBack() |
| { |
| d->page->goBack(); |
| } |
| |
| void QWebPage::goForward() |
| { |
| d->page->goForward(); |
| } |
| |
| void QWebPage::goToHistoryItem(const QWebHistoryItem &item) |
| { |
| d->page->goToItem(item.d->item, FrameLoadTypeIndexedBackForward); |
| } |
| |
| void QWebPage::javaScriptConsoleMessage(const QString& message, unsigned int lineNumber, const QString& sourceID) |
| { |
| } |
| |
| void QWebPage::javaScriptAlert(QWebFrame *frame, const QString& msg) |
| { |
| //FIXME frame pos... |
| QMessageBox::information(this, title(), msg, QMessageBox::Ok); |
| } |
| |
| bool QWebPage::javaScriptConfirm(QWebFrame *frame, const QString& msg) |
| { |
| //FIXME frame pos... |
| return 0 == QMessageBox::information(this, title(), msg, QMessageBox::Yes, QMessageBox::No); |
| } |
| |
| bool QWebPage::javaScriptPrompt(QWebFrame *frame, const QString& msg, const QString& defaultValue, QString* result) |
| { |
| //FIXME frame pos... |
| bool ok = false; |
| #ifndef QT_NO_INPUTDIALOG |
| QString x = QInputDialog::getText(this, title(), msg, QLineEdit::Normal, defaultValue, &ok); |
| if (ok && result) { |
| *result = x; |
| } |
| #endif |
| return ok; |
| } |
| |
| QWebPage *QWebPage::createWindow() |
| { |
| return 0; |
| } |
| |
| QWebPage *QWebPage::createModalDialog() |
| { |
| return 0; |
| } |
| |
| QObject *QWebPage::createPlugin(const QString &classid, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues) |
| { |
| Q_UNUSED(classid) |
| Q_UNUSED(url) |
| Q_UNUSED(paramNames) |
| Q_UNUSED(paramValues) |
| return 0; |
| } |
| |
| QWebPage::NavigationRequestResponse QWebPage::navigationRequested(QWebFrame *frame, const QWebNetworkRequest &request, QWebPage::NavigationType type) |
| { |
| Q_UNUSED(request) |
| return AcceptNavigationRequest; |
| } |
| |
| void QWebPage::setWindowGeometry(const QRect& geom) |
| { |
| Q_UNUSED(geom) |
| } |
| |
| bool QWebPage::canCut() const |
| { |
| return d->page->focusController()->focusedOrMainFrame()->editor()->canCut(); |
| } |
| |
| bool QWebPage::canCopy() const |
| { |
| return d->page->focusController()->focusedOrMainFrame()->editor()->canCopy(); |
| } |
| |
| bool QWebPage::canPaste() const |
| { |
| return d->page->focusController()->focusedOrMainFrame()->editor()->canPaste(); |
| } |
| |
| void QWebPage::cut() |
| { |
| d->page->focusController()->focusedOrMainFrame()->editor()->cut(); |
| } |
| |
| void QWebPage::copy() |
| { |
| d->page->focusController()->focusedOrMainFrame()->editor()->copy(); |
| } |
| |
| void QWebPage::paste() |
| { |
| d->page->focusController()->focusedOrMainFrame()->editor()->paste(); |
| } |
| |
| /*! |
| Returns true if the page contains unsubmitted form data. |
| */ |
| bool QWebPage::isModified() const |
| { |
| return d->modified; |
| } |
| |
| |
| QUndoStack *QWebPage::undoStack() |
| { |
| if (!d->undoStack) |
| d->undoStack = new QUndoStack(this); |
| |
| return d->undoStack; |
| } |
| |
| static inline DragOperation dropActionToDragOp(Qt::DropActions actions) |
| { |
| unsigned result = 0; |
| if (actions & Qt::CopyAction) |
| result |= DragOperationCopy; |
| if (actions & Qt::MoveAction) |
| result |= DragOperationMove; |
| if (actions & Qt::LinkAction) |
| result |= DragOperationLink; |
| return (DragOperation)result; |
| } |
| |
| static inline Qt::DropAction dragOpToDropAction(unsigned actions) |
| { |
| Qt::DropAction result = Qt::IgnoreAction; |
| if (actions & DragOperationCopy) |
| result = Qt::CopyAction; |
| else if (actions & DragOperationMove) |
| result = Qt::MoveAction; |
| else if (actions & DragOperationLink) |
| result = Qt::LinkAction; |
| return result; |
| } |
| |
| void QWebPage::resizeEvent(QResizeEvent *e) |
| { |
| QWidget::resizeEvent(e); |
| if (mainFrame()->d->frame && mainFrame()->d->frameView) { |
| mainFrame()->d->frameView->setFrameGeometry(rect()); |
| mainFrame()->d->frame->forceLayout(); |
| mainFrame()->d->frame->view()->adjustViewSize(); |
| } |
| } |
| |
| void QWebPage::paintEvent(QPaintEvent *ev) |
| { |
| #ifdef QWEBKIT_TIME_RENDERING |
| QTime time; |
| time.start(); |
| #endif |
| |
| QPainter p(this); |
| |
| QVector<QRect> vector = ev->region().rects(); |
| if (!vector.isEmpty()) { |
| for (int i = 0; i < vector.size(); ++i) { |
| mainFrame()->render(&p, vector.at(i)); |
| } |
| } else { |
| mainFrame()->render(&p, ev->rect()); |
| } |
| |
| #ifdef QWEBKIT_TIME_RENDERING |
| int elapsed = time.elapsed(); |
| qDebug()<<"paint event on "<<ev->region()<<", took to render = "<<elapsed; |
| #endif |
| } |
| |
| void QWebPage::mouseMoveEvent(QMouseEvent *ev) |
| { |
| mainFrame()->mouseMoveEvent(ev); |
| } |
| |
| void QWebPage::mousePressEvent(QMouseEvent *ev) |
| { |
| mainFrame()->mousePressEvent(ev); |
| } |
| |
| void QWebPage::mouseDoubleClickEvent(QMouseEvent *ev) |
| { |
| mainFrame()->mouseDoubleClickEvent(ev); |
| } |
| |
| void QWebPage::mouseReleaseEvent(QMouseEvent *ev) |
| { |
| mainFrame()->mouseReleaseEvent(ev); |
| } |
| |
| void QWebPage::wheelEvent(QWheelEvent *ev) |
| { |
| mainFrame()->wheelEvent(ev); |
| if (!ev->isAccepted()) |
| QWidget::wheelEvent(ev); |
| } |
| |
| void QWebPage::keyPressEvent(QKeyEvent *ev) |
| { |
| PlatformKeyboardEvent kevent(ev, false); |
| |
| if (!mainFrame()->d->eventHandler) |
| return; |
| |
| bool handled = mainFrame()->d->eventHandler->keyEvent(kevent); |
| if (handled) { |
| } else { |
| handled = true; |
| PlatformScrollbar *h, *v; |
| h = mainFrame()->d->horizontalScrollBar(); |
| v = mainFrame()->d->verticalScrollBar(); |
| |
| if (ev == QKeySequence::MoveToNextPage) { |
| if (v) |
| v->setValue(v->value() + height()); |
| } else if (ev == QKeySequence::MoveToPreviousPage) { |
| if (v) |
| v->setValue(v->value() - height()); |
| } else { |
| switch (ev->key()) { |
| case Qt::Key_Up: |
| if (v) |
| v->setValue(v->value() - 10); |
| break; |
| case Qt::Key_Down: |
| if (v) |
| v->setValue(v->value() + 10); |
| break; |
| case Qt::Key_Left: |
| if (h) |
| h->setValue(h->value() - 10); |
| break; |
| case Qt::Key_Right: |
| if (h) |
| h->setValue(h->value() + 10); |
| break; |
| default: |
| handled = false; |
| break; |
| } |
| } |
| } |
| |
| ev->setAccepted(handled); |
| } |
| |
| void QWebPage::keyReleaseEvent(QKeyEvent *ev) |
| { |
| if (ev->isAutoRepeat()) { |
| ev->setAccepted(true); |
| return; |
| } |
| |
| PlatformKeyboardEvent kevent(ev, true); |
| |
| if (!mainFrame()->d->eventHandler) |
| return; |
| |
| bool handled = mainFrame()->d->eventHandler->keyEvent(kevent); |
| ev->setAccepted(handled); |
| } |
| |
| void QWebPage::focusInEvent(QFocusEvent *ev) |
| { |
| if (ev->reason() != Qt::PopupFocusReason) { |
| mainFrame()->d->frame->page()->focusController()->setFocusedFrame(mainFrame()->d->frame); |
| mainFrame()->d->frame->setIsActive(true); |
| } |
| QWidget::focusInEvent(ev); |
| } |
| |
| void QWebPage::focusOutEvent(QFocusEvent *ev) |
| { |
| QWidget::focusOutEvent(ev); |
| if (ev->reason() != Qt::PopupFocusReason) { |
| mainFrame()->d->frame->selectionController()->clear(); |
| mainFrame()->d->frame->setIsActive(false); |
| } |
| } |
| |
| bool QWebPage::focusNextPrevChild(bool next) |
| { |
| Q_UNUSED(next) |
| return false; |
| } |
| |
| void QWebPage::dragEnterEvent(QDragEnterEvent *ev) |
| { |
| #ifndef QT_NO_DRAGANDDROP |
| DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(), |
| dropActionToDragOp(ev->possibleActions())); |
| Qt::DropAction action = dragOpToDropAction(d->page->dragController()->dragEntered(&dragData)); |
| ev->setDropAction(action); |
| ev->accept(); |
| #endif |
| } |
| |
| void QWebPage::dragLeaveEvent(QDragLeaveEvent *ev) |
| { |
| #ifndef QT_NO_DRAGANDDROP |
| DragData dragData(0, IntPoint(), QCursor::pos(), DragOperationNone); |
| d->page->dragController()->dragExited(&dragData); |
| ev->accept(); |
| #endif |
| } |
| |
| void QWebPage::dragMoveEvent(QDragMoveEvent *ev) |
| { |
| #ifndef QT_NO_DRAGANDDROP |
| DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(), |
| dropActionToDragOp(ev->possibleActions())); |
| Qt::DropAction action = dragOpToDropAction(d->page->dragController()->dragUpdated(&dragData)); |
| ev->setDropAction(action); |
| ev->accept(); |
| #endif |
| } |
| |
| void QWebPage::dropEvent(QDropEvent *ev) |
| { |
| #ifndef QT_NO_DRAGANDDROP |
| DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(), |
| dropActionToDragOp(ev->possibleActions())); |
| Qt::DropAction action = dragOpToDropAction(d->page->dragController()->performDrag(&dragData)); |
| ev->accept(); |
| #endif |
| } |
| |
| void QWebPage::setNetworkInterface(QWebNetworkInterface *interface) |
| { |
| d->networkInterface = interface; |
| } |
| |
| QWebNetworkInterface *QWebPage::networkInterface() const |
| { |
| if (d->networkInterface) |
| return d->networkInterface; |
| else |
| return QWebNetworkInterface::defaultInterface(); |
| } |
| |
| QPixmap QWebPage::icon() const |
| { |
| Image* image = iconDatabase()->iconForPageURL(url().toString(), IntSize(16, 16)); |
| if (!image || image->isNull()) { |
| image = iconDatabase()->defaultIcon(IntSize(16, 16)); |
| } |
| |
| if (!image) { |
| return QPixmap(); |
| } |
| |
| QPixmap *icon = image->getPixmap(); |
| if (!icon) { |
| return QPixmap(); |
| } |
| return *icon; |
| } |
| |
| void QWebPage::setSettings(const QWebSettings &settings) |
| { |
| WebCore::Settings *wSettings = d->page->settings(); |
| |
| wSettings->setStandardFontFamily( |
| settings.fontFamily(QWebSettings::StandardFont)); |
| wSettings->setFixedFontFamily( |
| settings.fontFamily(QWebSettings::FixedFont)); |
| wSettings->setSerifFontFamily( |
| settings.fontFamily(QWebSettings::SerifFont)); |
| wSettings->setSansSerifFontFamily( |
| settings.fontFamily(QWebSettings::SansSerifFont)); |
| wSettings->setCursiveFontFamily( |
| settings.fontFamily(QWebSettings::CursiveFont)); |
| wSettings->setFantasyFontFamily( |
| settings.fontFamily(QWebSettings::FantasyFont)); |
| |
| wSettings->setMinimumFontSize(settings.minimumFontSize()); |
| wSettings->setMinimumLogicalFontSize(settings.minimumLogicalFontSize()); |
| wSettings->setDefaultFontSize(settings.defaultFontSize()); |
| wSettings->setDefaultFixedFontSize(settings.defaultFixedFontSize()); |
| |
| wSettings->setLoadsImagesAutomatically( |
| settings.testAttribute(QWebSettings::AutoLoadImages)); |
| wSettings->setJavaScriptEnabled( |
| settings.testAttribute(QWebSettings::JavascriptEnabled)); |
| wSettings->setJavaScriptCanOpenWindowsAutomatically( |
| settings.testAttribute(QWebSettings::JavascriptCanOpenWindows)); |
| wSettings->setJavaEnabled( |
| settings.testAttribute(QWebSettings::JavaEnabled)); |
| wSettings->setPluginsEnabled( |
| settings.testAttribute(QWebSettings::PluginsEnabled)); |
| wSettings->setPrivateBrowsingEnabled( |
| settings.testAttribute(QWebSettings::PrivateBrowsingEnabled)); |
| |
| wSettings->setUserStyleSheetLocation(KURL(settings.userStyleSheetLocation())); |
| |
| // ### should be configurable |
| wSettings->setDefaultTextEncodingName("iso-8859-1"); |
| } |
| |
| QWebSettings QWebPage::settings() const |
| { |
| QWebSettings settings; |
| WebCore::Settings *wSettings = d->page->settings(); |
| |
| settings.setFontFamily(QWebSettings::StandardFont, |
| wSettings->standardFontFamily()); |
| settings.setFontFamily(QWebSettings::FixedFont, |
| wSettings->fixedFontFamily()); |
| settings.setFontFamily(QWebSettings::SerifFont, |
| wSettings->serifFontFamily()); |
| settings.setFontFamily(QWebSettings::SansSerifFont, |
| wSettings->sansSerifFontFamily()); |
| settings.setFontFamily(QWebSettings::CursiveFont, |
| wSettings->cursiveFontFamily()); |
| settings.setFontFamily(QWebSettings::FantasyFont, |
| wSettings->fantasyFontFamily()); |
| |
| settings.setMinimumFontSize(wSettings->minimumFontSize()); |
| settings.setMinimumLogicalFontSize(wSettings->minimumLogicalFontSize()); |
| settings.setDefaultFontSize(wSettings->defaultFontSize()); |
| settings.setDefaultFixedFontSize(wSettings->defaultFixedFontSize()); |
| |
| settings.setAttribute(QWebSettings::AutoLoadImages, |
| wSettings->loadsImagesAutomatically()); |
| settings.setAttribute(QWebSettings::JavascriptEnabled, |
| wSettings->isJavaScriptEnabled()); |
| settings.setAttribute(QWebSettings::JavascriptCanOpenWindows, |
| wSettings->JavaScriptCanOpenWindowsAutomatically()); |
| settings.setAttribute(QWebSettings::JavaEnabled, |
| wSettings->isJavaEnabled()); |
| settings.setAttribute(QWebSettings::PluginsEnabled, |
| wSettings->arePluginsEnabled()); |
| settings.setAttribute(QWebSettings::PrivateBrowsingEnabled, |
| wSettings->privateBrowsingEnabled()); |
| |
| settings.setUserStyleSheetLocation( |
| wSettings->userStyleSheetLocation().url()); |
| |
| return settings; |
| } |
| |
| QString QWebPage::chooseFile(QWebFrame *parentFrame, const QString& oldFile) |
| { |
| //FIXME frame pos... |
| #ifndef QT_NO_FILEDIALOG |
| return QFileDialog::getOpenFileName(this, QString::null, oldFile); |
| #else |
| return QString::null; |
| #endif |
| } |
| |
| #ifndef QT_NO_NETWORKPROXY |
| void QWebPage::setNetworkProxy(const QNetworkProxy& proxy) |
| { |
| d->networkProxy = proxy; |
| } |
| |
| QNetworkProxy QWebPage::networkProxy() const |
| { |
| return d->networkProxy; |
| } |
| #endif |
| |
| QString QWebPage::userAgentStringForUrl(const QUrl& forUrl) const { |
| Q_UNUSED(forUrl) |
| return QLatin1String("Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWebKit/418.9.1 (KHTML, like Gecko) Safari/419.3 Qt"); |
| } |
| |
| |
| void QWebPage::onLoadProgressChanged(int) { |
| d->m_totalBytes = d->page->progress()->totalPageAndResourceBytesToLoad(); |
| d->m_bytesReceived = d->page->progress()->totalBytesReceived(); |
| } |
| |
| |
| quint64 QWebPage::totalBytes() const { |
| return d->m_bytesReceived; |
| } |
| |
| |
| quint64 QWebPage::bytesReceived() const { |
| return d->m_totalBytes; |
| } |