• Jocelyn Turcotte's avatar
    Base load signals on Blink loader events · f06cb10c
    Jocelyn Turcotte authored
    
    This mainly remove the use of the LoadingStateChanged callback, which
    is tied to DidStartLoading and DidStopLoading.
    Those signals are handled from the browser process side, also wrapping
    the time where the render process is initialized. We can't rely on
    those signals for loadStarted, but afterward rely on the Blink loader
    for loadFinished. We must use the same source for both.
    
    Instead only rely on Blink callbacks ultimately related to network
    events. This gives us a behavior closer to QtWebKit.
    
    The major compromise that this forces us to to accept is that
    loadStarted is now triggered asynchronously. This will basically break
    anything expecting loadStarted to be emitted synchronously from the
    load method.
    
    This also adjust autotests to get a few more passing.
    
    Initial-patch-by: default avatarPierre Rossi <pierre.rossi@digia.com>
    Change-Id: Ib6c0170df891d1b7f8ed4dc1d483985523e267dc
    Reviewed-by: default avatarPierre Rossi <pierre.rossi@gmail.com>
    Reviewed-by: default avatarSimon Hausmann <simon.hausmann@digia.com>
    f06cb10c
qwebenginepage.cpp 25.24 KiB
/*
    Copyright (C) 2012, 2013 Digia Plc and/or its subsidiary(-ies).
    Copyright (C) 2008, 2009, 2012 Nokia Corporation and/or its subsidiary(-ies)
    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.
#include "qwebenginepage.h"
#include "qwebenginepage_p.h"
#include "javascript_dialog_controller.h"
#include "qwebenginehistory.h"
#include "qwebenginehistory_p.h"
#include "qwebengineview.h"
#include "qwebengineview_p.h"
#include "render_widget_host_view_qt_delegate_popup.h"
#include "render_widget_host_view_qt_delegate_webpage.h"
#include "web_contents_adapter.h"
#include <QAction>
#include <QApplication>
#include <QClipboard>
#include <QFileDialog>
#include <QIcon>
#include <QInputDialog>
#include <QMenu>
#include <QMessageBox>
#include <QStandardPaths>
#include <QUrl>
#include <private/qauthenticator_p.h>
QT_BEGIN_NAMESPACE
CallbackDirectory::~CallbackDirectory()
    // "Cancel" pending callbacks by calling them with an invalid value.
    // This guarantees that each callback is called exactly once.
    Q_FOREACH (const CallbackSharedDataPointer &sharedPtr, m_callbackMap) {
        switch (sharedPtr.type) {
        case CallbackSharedDataPointer::Variant:
            (*sharedPtr.variantCallback)(QVariant());
            break;
        case CallbackSharedDataPointer::String:
            (*sharedPtr.stringCallback)(QString());
            break;
        case CallbackSharedDataPointer::Bool:
            (*sharedPtr.boolCallback)(false);
            break;
        default:
            Q_UNREACHABLE();
void CallbackDirectory::registerCallback(quint64 requestId, const QExplicitlySharedDataPointer<VariantCallback> &callback)
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
{ m_callbackMap.insert(requestId, CallbackSharedDataPointer(callback.data())); } void CallbackDirectory::registerCallback(quint64 requestId, const QExplicitlySharedDataPointer<StringCallback> &callback) { m_callbackMap.insert(requestId, CallbackSharedDataPointer(callback.data())); } void CallbackDirectory::registerCallback(quint64 requestId, const QExplicitlySharedDataPointer<BoolCallback> &callback) { m_callbackMap.insert(requestId, CallbackSharedDataPointer(callback.data())); } void CallbackDirectory::invoke(quint64 requestId, const QVariant &result) { CallbackSharedDataPointer sharedPtr = m_callbackMap.take(requestId); if (sharedPtr) { Q_ASSERT(sharedPtr.type == CallbackSharedDataPointer::Variant); (*sharedPtr.variantCallback)(result); } } void CallbackDirectory::invoke(quint64 requestId, const QString &result) { CallbackSharedDataPointer sharedPtr = m_callbackMap.take(requestId); if (sharedPtr) { Q_ASSERT(sharedPtr.type == CallbackSharedDataPointer::String); (*sharedPtr.stringCallback)(result); } } void CallbackDirectory::invoke(quint64 requestId, bool result) { CallbackSharedDataPointer sharedPtr = m_callbackMap.take(requestId); if (sharedPtr) { Q_ASSERT(sharedPtr.type == CallbackSharedDataPointer::Bool); (*sharedPtr.boolCallback)(result); } } void CallbackDirectory::CallbackSharedDataPointer::doRef() { switch (type) { case None: break; case Variant: variantCallback->ref.ref(); break; case String: stringCallback->ref.ref(); break; case Bool: boolCallback->ref.ref(); break; } } void CallbackDirectory::CallbackSharedDataPointer::doDeref() { switch (type) { case None: break; case Variant: if (!variantCallback->ref.deref()) delete variantCallback; break; case String: if (!stringCallback->ref.deref()) delete stringCallback;
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
break; case Bool: if (!boolCallback->ref.deref()) delete boolCallback; break; } } QWebEnginePagePrivate::QWebEnginePagePrivate() : QObjectPrivate(QObjectPrivateVersion) , adapter(new WebContentsAdapter(SoftwareRenderingMode)) , history(new QWebEngineHistory(new QWebEngineHistoryPrivate(adapter.data()))) , view(0) { memset(actions, 0, sizeof(actions)); } QWebEnginePagePrivate::~QWebEnginePagePrivate() { delete history; } RenderWidgetHostViewQtDelegate *QWebEnginePagePrivate::CreateRenderWidgetHostViewQtDelegate(RenderWidgetHostViewQtDelegateClient *client, RenderingMode mode) { Q_UNUSED(mode); return new RenderWidgetHostViewQtDelegateWebPage(client); } RenderWidgetHostViewQtDelegate *QWebEnginePagePrivate::CreateRenderWidgetHostViewQtDelegateForPopup(RenderWidgetHostViewQtDelegateClient *client, WebContentsAdapterClient::RenderingMode) { Q_ASSERT(m_rwhvDelegate); return new RenderWidgetHostViewQtDelegatePopup(client, view); } void QWebEnginePagePrivate::titleChanged(const QString &title) { Q_Q(QWebEnginePage); Q_EMIT q->titleChanged(title); } void QWebEnginePagePrivate::urlChanged(const QUrl &url) { Q_Q(QWebEnginePage); m_explicitUrl = QUrl(); Q_EMIT q->urlChanged(url); } void QWebEnginePagePrivate::iconChanged(const QUrl &url) { Q_UNUSED(url) } void QWebEnginePagePrivate::loadProgressChanged(int progress) { Q_Q(QWebEnginePage); Q_EMIT q->loadProgress(progress); } void QWebEnginePagePrivate::selectionChanged() { Q_Q(QWebEnginePage); Q_EMIT q->selectionChanged(); } QRectF QWebEnginePagePrivate::viewportRect() const { QRectF rect(QPointF(), viewportSize); if (view) rect.setTopLeft(view->rect().topLeft()); return rect;
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
} qreal QWebEnginePagePrivate::dpiScale() const { return 1.0; } void QWebEnginePagePrivate::loadStarted(const QUrl &provisionalUrl) { Q_UNUSED(provisionalUrl) Q_Q(QWebEnginePage); Q_EMIT q->loadStarted(); updateNavigationActions(); } void QWebEnginePagePrivate::loadCommitted() { updateNavigationActions(); } void QWebEnginePagePrivate::loadFinished(bool success, int error_code, const QString &error_description) { Q_Q(QWebEnginePage); Q_UNUSED(error_code); Q_UNUSED(error_description); if (success) m_explicitUrl = QUrl(); Q_EMIT q->loadFinished(success); updateNavigationActions(); } void QWebEnginePagePrivate::focusContainer() { if (view) view->setFocus(); } void QWebEnginePagePrivate::adoptNewWindow(WebContentsAdapter *newWebContents, WindowOpenDisposition disposition, const QRect &initialGeometry) { Q_Q(QWebEnginePage); QWebEnginePage *newPage = q->createWindow(disposition == WebContentsAdapterClient::NewPopupDisposition ? QWebEnginePage::WebModalDialog : QWebEnginePage::WebBrowserWindow); // Overwrite the new page's WebContents with ours. if (newPage) { newPage->d_func()->adapter = newWebContents; newPage->history()->d_func()->adapter = newWebContents; newWebContents->initialize(newPage->d_func()); if (!initialGeometry.isEmpty()) emit newPage->geometryChangeRequested(initialGeometry); } } void QWebEnginePagePrivate::close() { Q_Q(QWebEnginePage); Q_EMIT q->windowCloseRequested(); } void QWebEnginePagePrivate::didRunJavaScript(quint64 requestId, const QVariant& result) { m_callbacks.invoke(requestId, result); } void QWebEnginePagePrivate::didFetchDocumentMarkup(quint64 requestId, const QString& result) { m_callbacks.invoke(requestId, result); } void QWebEnginePagePrivate::didFetchDocumentInnerText(quint64 requestId, const QString& result) { m_callbacks.invoke(requestId, result);
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
} void QWebEnginePagePrivate::didFindText(quint64 requestId, int matchCount) { m_callbacks.invoke(requestId, matchCount > 0); } void QWebEnginePagePrivate::authenticationRequired(const QUrl &requestUrl, const QString &realm, bool isProxy, const QString &challengingHost, QString *outUser, QString *outPassword) { Q_Q(QWebEnginePage); QAuthenticator networkAuth; // Detach to trigger the creation of its QAuthenticatorPrivate. networkAuth.detach(); QAuthenticatorPrivate::getPrivate(networkAuth)->realm = realm; if (isProxy) Q_EMIT q->proxyAuthenticationRequired(requestUrl, &networkAuth, challengingHost); else Q_EMIT q->authenticationRequired(requestUrl, &networkAuth); *outUser = networkAuth.user(); *outPassword = networkAuth.password(); } void QWebEnginePagePrivate::updateAction(QWebEnginePage::WebAction action) const { #ifdef QT_NO_ACTION Q_UNUSED(action) #else QAction *a = actions[action]; if (!a) return; bool enabled = true; switch (action) { case QWebEnginePage::Back: enabled = adapter->canGoBack(); break; case QWebEnginePage::Forward: enabled = adapter->canGoForward(); break; case QWebEnginePage::Stop: enabled = adapter->isLoading(); break; case QWebEnginePage::Reload: case QWebEnginePage::ReloadAndBypassCache: enabled = !adapter->isLoading(); break; default: break; } a->setEnabled(enabled); #endif // QT_NO_ACTION } void QWebEnginePagePrivate::updateNavigationActions() { updateAction(QWebEnginePage::Back); updateAction(QWebEnginePage::Forward); updateAction(QWebEnginePage::Stop); updateAction(QWebEnginePage::Reload); updateAction(QWebEnginePage::ReloadAndBypassCache); } #ifndef QT_NO_ACTION void QWebEnginePagePrivate::_q_webActionTriggered(bool checked) { Q_Q(QWebEnginePage); QAction *a = qobject_cast<QAction *>(q->sender());
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
if (!a) return; QWebEnginePage::WebAction action = static_cast<QWebEnginePage::WebAction>(a->data().toInt()); q->triggerAction(action, checked); } #endif // QT_NO_ACTION QWebEnginePage::QWebEnginePage(QObject* parent) : QObject(*new QWebEnginePagePrivate, parent) { Q_D(QWebEnginePage); d->adapter->initialize(d); } QWebEnginePage::~QWebEnginePage() { Q_D(QWebEnginePage); QWebEngineViewPrivate::bind(d->view, 0); } QWebEngineHistory *QWebEnginePage::history() const { Q_D(const QWebEnginePage); return d->history; } void QWebEnginePage::setView(QWidget *view) { QWebEngineViewPrivate::bind(qobject_cast<QWebEngineView*>(view), this); } QWidget *QWebEnginePage::view() const { Q_D(const QWebEnginePage); return d->view; } bool QWebEnginePage::hasSelection() const { return !selectedText().isEmpty(); } QString QWebEnginePage::selectedText() const { Q_D(const QWebEnginePage); return d->adapter->selectedText(); } #ifndef QT_NO_ACTION QAction *QWebEnginePage::action(WebAction action) const { Q_D(const QWebEnginePage); if (action == QWebEnginePage::NoWebAction) return 0; if (d->actions[action]) return d->actions[action]; QString text; QIcon icon; QStyle *style = d->view ? d->view->style() : qApp->style(); switch (action) { case Back: text = tr("Back"); icon = style->standardIcon(QStyle::SP_ArrowBack); break; case Forward: text = tr("Forward"); icon = style->standardIcon(QStyle::SP_ArrowForward); break;
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
case Stop: text = tr("Stop"); icon = style->standardIcon(QStyle::SP_BrowserStop); break; case Reload: text = tr("Reload"); icon = style->standardIcon(QStyle::SP_BrowserReload); break; case Cut: text = tr("Cut"); break; case Copy: text = tr("Copy"); break; case Paste: text = tr("Paste"); break; case Undo: text = tr("Undo"); break; case Redo: text = tr("Redo"); break; case SelectAll: text = tr("Select All"); break; case PasteAndMatchStyle: text = tr("Paste and Match Style"); break; default: break; } QAction *a = new QAction(const_cast<QWebEnginePage*>(this)); a->setText(text); a->setData(action); a->setIcon(icon); connect(a, SIGNAL(triggered(bool)), this, SLOT(_q_webActionTriggered(bool))); d->actions[action] = a; d->updateAction(action); return a; } #endif // QT_NO_ACTION void QWebEnginePage::triggerAction(WebAction action, bool) { Q_D(QWebEnginePage); switch (action) { case Back: d->adapter->navigateToOffset(-1); break; case Forward: d->adapter->navigateToOffset(1); break; case Stop: d->adapter->stop(); break; case Reload: d->adapter->reload(); break; case Cut: d->adapter->cut(); break; case Copy: d->adapter->copy(); break; case Paste: d->adapter->paste();
491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
break; case Undo: d->adapter->undo(); break; case Redo: d->adapter->redo(); break; case SelectAll: d->adapter->selectAll(); break; case PasteAndMatchStyle: d->adapter->pasteAndMatchStyle(); break; default: Q_UNREACHABLE(); } } void QWebEnginePage::findText(const QString &subString, FindFlags options, const QWebEngineCallback<bool> &resultCallback) { Q_D(QWebEnginePage); if (subString.isEmpty()) { d->adapter->stopFinding(); if (resultCallback.d) (*resultCallback.d)(false); } else { quint64 requestId = d->adapter->findText(subString, options & FindCaseSensitively, options & FindBackward); if (resultCallback.d) d->m_callbacks.registerCallback(requestId, resultCallback.d); } } QSize QWebEnginePage::viewportSize() const { Q_D(const QWebEnginePage); return d->viewportSize; } void QWebEnginePage::setViewportSize(const QSize &size) { Q_D(QWebEnginePage); d->viewportSize = size; if (d->m_rwhvDelegate) d->m_rwhvDelegate->notifyResize(); } bool QWebEnginePage::event(QEvent *e) { Q_D(QWebEnginePage); if (!d->m_rwhvDelegate) { // FIXME: implement a signal when the render process crashes and keep track of it at this level // Ideally, this should be Q_ASSERT(!d->m_renderProcessLive) or something along those lines qWarning("%s: no render process running?\n", Q_FUNC_INFO); return false; } if (!d->m_rwhvDelegate->forwardEvent(e)) return QObject::event(e); return true; } bool QWebEnginePagePrivate::contextMenuRequested(const WebEngineContextMenuData &data) { if (!view) return false; QContextMenuEvent event(QContextMenuEvent::Mouse, data.pos, view->mapToGlobal(data.pos)); switch (view->contextMenuPolicy()) { case Qt::PreventContextMenu: return false; case Qt::DefaultContextMenu:
561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
m_menuData = data; view->contextMenuEvent(&event); break; case Qt::CustomContextMenu: Q_EMIT view->customContextMenuRequested(data.pos); break; case Qt::ActionsContextMenu: if (view->actions().count()) { QMenu::exec(view->actions(), event.globalPos(), 0, view); break; } // fall through default: event.ignore(); return false; break; } Q_ASSERT(view->d_func()->m_pendingContextMenuEvent); view->d_func()->m_pendingContextMenuEvent = false; m_menuData = WebEngineContextMenuData(); return true; } void QWebEnginePagePrivate::javascriptDialog(QSharedPointer<JavaScriptDialogController> controller) { Q_Q(QWebEnginePage); bool accepted = false; QString promptResult; switch (controller->type()) { case AlertDialog: q->javaScriptAlert(0, controller->message()); accepted = true; break; case ConfirmDialog: accepted = q->javaScriptConfirm(0, controller->message()); break; case PromptDialog: accepted = q->javaScriptPrompt(0, controller->message(), controller->defaultPrompt(), &promptResult); if (accepted) controller->textProvided(promptResult); break; default: Q_UNREACHABLE(); } if (accepted) controller->accept(); else controller->reject(); } void QWebEnginePagePrivate::javaScriptConsoleMessage(int level, const QString &message, int lineNumber, const QString &sourceID) { Q_Q(QWebEnginePage); q->javaScriptConsoleMessage(level, message, lineNumber, sourceID); } namespace { class SaveToClipboardFunctor { QString m_text; public: SaveToClipboardFunctor(const QString &text) : m_text(text) {} void operator()() const { qApp->clipboard()->setText(m_text); } };
631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
class LoadUrlFunctor { QWebEnginePage *m_page; QUrl m_url; public: LoadUrlFunctor(QWebEnginePage *page, const QUrl &url) : m_page(page) , m_url(url) {} void operator()() const { m_page->load(m_url); } }; } QMenu *QWebEnginePage::createStandardContextMenu() { Q_D(QWebEnginePage); QMenu *menu = new QMenu(d->view); QAction *action = 0; WebEngineContextMenuData contextMenuData(d->m_menuData); if (contextMenuData.selectedText.isEmpty()) { action = new QAction(QIcon::fromTheme(QStringLiteral("go-previous")), tr("&Back"), menu); connect(action, &QAction::triggered, d->view, &QWebEngineView::back); action->setEnabled(d->adapter->canGoBack()); menu->addAction(action); action = new QAction(QIcon::fromTheme(QStringLiteral("go-next")), tr("&Forward"), menu); connect(action, &QAction::triggered, d->view, &QWebEngineView::forward); action->setEnabled(d->adapter->canGoForward()); menu->addAction(action); action = new QAction(QIcon::fromTheme(QStringLiteral("view-refresh")), tr("&Reload"), menu); connect(action, &QAction::triggered, d->view, &QWebEngineView::reload); menu->addAction(action); } else { action = new QAction(tr("Copy..."), menu); connect(action, &QAction::triggered, SaveToClipboardFunctor(contextMenuData.selectedText)); menu->addAction(action); } if (!contextMenuData.linkText.isEmpty() && contextMenuData.linkUrl.isValid()) { menu->addSeparator(); action = new QAction(tr("Navigate to..."), menu); connect(action, &QAction::triggered, LoadUrlFunctor(this, contextMenuData.linkUrl)); menu->addAction(action); action = new QAction(tr("Copy link address"), menu); connect(action, &QAction::triggered, SaveToClipboardFunctor(contextMenuData.linkUrl.toString())); menu->addAction(action); } return menu; } static inline QWebEnginePage::FileSelectionMode toPublic(WebContentsAdapterClient::FileChooserMode mode) { // Should the underlying values change, we'll need a switch here. return static_cast<QWebEnginePage::FileSelectionMode>(mode); } void QWebEnginePagePrivate::runFileChooser(WebContentsAdapterClient::FileChooserMode mode, const QString &defaultFileName, const QStringList &acceptedMimeTypes) { Q_Q(QWebEnginePage); QStringList selectedFileNames = q->chooseFiles(toPublic(mode), (QStringList() << defaultFileName), acceptedMimeTypes); adapter->filesSelectedInChooser(selectedFileNames, mode); } void QWebEnginePage::load(const QUrl& url) { Q_D(QWebEnginePage);
701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
d->adapter->load(url); } void QWebEnginePage::toHtml(const QWebEngineCallback<const QString &> &resultCallback) const { Q_D(const QWebEnginePage); quint64 requestId = d->adapter->fetchDocumentMarkup(); d->m_callbacks.registerCallback(requestId, resultCallback.d); } void QWebEnginePage::toPlainText(const QWebEngineCallback<const QString &> &resultCallback) const { Q_D(const QWebEnginePage); quint64 requestId = d->adapter->fetchDocumentInnerText(); d->m_callbacks.registerCallback(requestId, resultCallback.d); } void QWebEnginePage::setHtml(const QString &html, const QUrl &baseUrl) { setContent(html.toUtf8(), QStringLiteral("text/html;charset=UTF-8"), baseUrl); } void QWebEnginePage::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl) { Q_D(QWebEnginePage); d->adapter->setContent(data, mimeType, baseUrl, baseUrl); } QString QWebEnginePage::title() const { Q_D(const QWebEnginePage); return d->adapter->pageTitle(); } void QWebEnginePage::setUrl(const QUrl &url) { Q_D(QWebEnginePage); d->m_explicitUrl = url; load(url); } QUrl QWebEnginePage::url() const { Q_D(const QWebEnginePage); return d->m_explicitUrl.isValid() ? d->m_explicitUrl : d->adapter->activeUrl(); } QUrl QWebEnginePage::requestedUrl() const { Q_D(const QWebEnginePage); return d->adapter->requestedUrl(); } void QWebEnginePage::render(QPainter *p, const QRegion &clip) { Q_D(const QWebEnginePage); if (!d->m_rwhvDelegate) { // Most likely the render process crashed. See QWebEnginePage::event return; } if (!clip.isNull()) { p->save(); p->setClipRegion(clip); } d->m_rwhvDelegate->paint(p, QRectF(clip.boundingRect())); if (!clip.isNull()) p->restore(); } qreal QWebEnginePage::zoomFactor() const
771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
{ Q_D(const QWebEnginePage); return d->adapter->currentZoomFactor(); } void QWebEnginePage::setZoomFactor(qreal factor) { Q_D(QWebEnginePage); d->adapter->setZoomFactor(factor); } bool QWebEnginePage::hasFocus() const { Q_D(const QWebEnginePage); if (d->view) return d->view->hasFocus(); return false; } void QWebEnginePage::setFocus() { Q_D(QWebEnginePage); if (d->view) d->view->setFocus(); } void QWebEnginePage::runJavaScript(const QString &scriptSource, const QString &xPath) { Q_D(QWebEnginePage); d->adapter->runJavaScript(scriptSource, xPath); } void QWebEnginePage::runJavaScript(const QString& scriptSource, const QWebEngineCallback<const QVariant &> &resultCallback, const QString &xPath) { Q_D(QWebEnginePage); quint64 requestId = d->adapter->runJavaScriptCallbackResult(scriptSource, xPath); d->m_callbacks.registerCallback(requestId, resultCallback.d); } QWebEnginePage *QWebEnginePage::createWindow(WebWindowType type) { Q_D(QWebEnginePage); if (d->view) { QWebEngineView *newView = d->view->createWindow(type); if (newView) return newView->page(); } return 0; } Q_STATIC_ASSERT_X(static_cast<int>(WebContentsAdapterClient::Open) == static_cast<int>(QWebEnginePage::FileSelectOpen), "Enums out of sync"); Q_STATIC_ASSERT_X(static_cast<int>(WebContentsAdapterClient::OpenMultiple) == static_cast<int>(QWebEnginePage::FileSelectOpenMultiple), "Enums out of sync"); QStringList QWebEnginePage::chooseFiles(FileSelectionMode mode, const QStringList &oldFiles, const QStringList &acceptedMimeTypes) { // FIXME: Should we expose this in QWebPage's API ? Right now it is very open and can contain a mix and match of file extensions (which QFileDialog // can work with) and mimetypes ranging from text/plain or images/* to application/vnd.openxmlformats-officedocument.spreadsheetml.sheet Q_UNUSED(acceptedMimeTypes); QStringList ret; switch (static_cast<WebContentsAdapterClient::FileChooserMode>(mode)) { case WebContentsAdapterClient::OpenMultiple: ret = QFileDialog::getOpenFileNames(view(), QString()); break; // Chromium extension, not exposed as part of the public API for now. case WebContentsAdapterClient::UploadFolder: ret << QFileDialog::getExistingDirectory(view(), tr("Select folder to upload")) + QLatin1Char('/'); break; case WebContentsAdapterClient::Save: ret << QFileDialog::getSaveFileName(view(), QString(), (QStandardPaths::writableLocation(QStandardPaths::DownloadLocation) + oldFiles.first())); break;
841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880
default: case WebContentsAdapterClient::Open: ret << QFileDialog::getOpenFileName(view(), QString(), oldFiles.first()); break; } return ret; } void QWebEnginePage::javaScriptAlert(QWebEngineFrame *originatingFrame, const QString &msg) { Q_UNUSED(originatingFrame); QMessageBox::information(view(), QStringLiteral("Javascript Alert - %1").arg(url().toString()), msg); } bool QWebEnginePage::javaScriptConfirm(QWebEngineFrame *originatingFrame, const QString &msg) { Q_UNUSED(originatingFrame); return (QMessageBox::information(view(), QStringLiteral("Javascript Confirm - %1").arg(url().toString()), msg, QMessageBox::Ok, QMessageBox::Cancel) == QMessageBox::Ok); } bool QWebEnginePage::javaScriptPrompt(QWebEngineFrame *originatingFrame, const QString &msg, const QString &defaultValue, QString *result) { Q_UNUSED(originatingFrame); bool ret = false; if (result) *result = QInputDialog::getText(view(), QStringLiteral("Javascript Prompt - %1").arg(url().toString()), msg, QLineEdit::Normal, defaultValue, &ret); return ret; } void QWebEnginePage::javaScriptConsoleMessage(int level, const QString &message, int lineNumber, const QString &sourceID) { Q_UNUSED(level); Q_UNUSED(message); Q_UNUSED(lineNumber); Q_UNUSED(sourceID); } QT_END_NAMESPACE #include "moc_qwebenginepage.cpp"