An error occurred while loading the file. Please try again.
-
Jocelyn Turcotte authored
Change-Id: I87c18edb89658433d6dc3487ab92d2ff7bd6c986 Reviewed-by:
Simon Hausmann <simon.hausmann@digia.com>
0bb596fb
/*
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);