qwebenginepage.cpp 20.34 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>
QT_BEGIN_NAMESPACE
QWebEnginePagePrivate::QWebEnginePagePrivate()
    : QObjectPrivate(QObjectPrivateVersion)
    , adapter(new WebContentsAdapter(SoftwareRenderingMode))
    , history(new QWebEngineHistory(new QWebEngineHistoryPrivate(adapter.data())))
    , view(0)
    , m_isLoading(false)
    memset(actions, 0, sizeof(actions));
QWebEnginePagePrivate::~QWebEnginePagePrivate()
    // "Cancel" pending callbacks by calling them with an invalid value.
    // This guarantees that each callback is called exactly once.
    Q_FOREACH (QExplicitlySharedDataPointer<VariantCallback> callback, m_variantCallbacks)
        (*callback)(QVariant());
    m_variantCallbacks.clear();
    Q_FOREACH (QExplicitlySharedDataPointer<StringCallback> callback, m_stringCallbacks)
        (*callback)(QString());
    m_stringCallbacks.clear();
    delete history;
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
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::loadingStateChanged() { Q_Q(QWebEnginePage); const bool wasLoading = m_isLoading; m_isLoading = adapter->isLoading(); if (m_isLoading != wasLoading) { if (m_isLoading) Q_EMIT q->loadStarted(); } updateNavigationActions(); } void QWebEnginePagePrivate::loadProgressChanged(int progress) { Q_Q(QWebEnginePage); Q_EMIT q->loadProgress(progress); } QRectF QWebEnginePagePrivate::viewportRect() const { return view ? view->geometry() : QRectF(); } qreal QWebEnginePagePrivate::dpiScale() const { return 1.0; } void QWebEnginePagePrivate::loadFinished(bool success, int error_code, const QString &error_description) { Q_Q(QWebEnginePage); Q_UNUSED(error_code); Q_UNUSED(error_description); m_isLoading = adapter->isLoading(); if (success) m_explicitUrl = QUrl(); Q_EMIT q->loadFinished(success); }
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
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; 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(const QVariant& result, quint64 requestId) { if (QExplicitlySharedDataPointer<VariantCallback> callback = m_variantCallbacks.take(requestId)) (*callback)(result); } void QWebEnginePagePrivate::didFetchDocumentMarkup(const QString& result, quint64 requestId) { if (QExplicitlySharedDataPointer<StringCallback> callback = m_stringCallbacks.take(requestId)) (*callback)(result); } void QWebEnginePagePrivate::didFetchDocumentInnerText(const QString& result, quint64 requestId) { if (QExplicitlySharedDataPointer<StringCallback> callback = m_stringCallbacks.take(requestId)) (*callback)(result); } void QWebEnginePagePrivate::updateAction(QWebEnginePage::WebAction action) const { #ifdef QT_NO_ACTION Q_UNUSED(action) #else QAction *a = actions[action]; if (!a) return; bool enabled = false; 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;
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
} 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()); 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; } #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();
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
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; case Stop: text = tr("Stop"); icon = style->standardIcon(QStyle::SP_BrowserStop); break; case Reload: text = tr("Reload"); icon = style->standardIcon(QStyle::SP_BrowserReload); 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; default: Q_UNREACHABLE(); } } void QWebEnginePage::setViewportSize(const QSize &size) const { Q_UNUSED(size) Q_D(const QWebEnginePage); 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);