diff options
109 files changed, 2200 insertions, 489 deletions
diff --git a/dist/changes-5.7.0 b/dist/changes-5.7.0 new file mode 100644 index 000000000..8b6e302b8 --- /dev/null +++ b/dist/changes-5.7.0 @@ -0,0 +1,79 @@ +Qt 5.7 introduces many new features and improvements as well as bugfixes +over the 5.6.x series. For more details, refer to the online documentation +included in this distribution. The documentation is also available online: + + http://doc.qt.io/qt-5/index.html + +The Qt version 5.7 series is binary compatible with the 5.6.x series. +Applications compiled for 5.6 will continue to run with 5.7. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* General * +**************************************************************************** + + - Chromium Snapshot: + * The Chromium version has been updated to 49.0.2623.111. + * In addition security fixes from Chromium 50 have been merged. + + - Web Features: + * Drag'n'drop is now supported + * Encrypted Media Extensions EME is now supported + if the PPAPI Widevine CDM plugin is installed. + * Spellchecking is now available if dictionaries are installed. + +**************************************************************************** +* Qt WebEngineQML * +**************************************************************************** + + - WebEngineView: + * New WebAction for saving page on disk in multiple different formats + including MHTML. + * JavaScript can now be executed in separate worlds. + * WebChannels can now be installed in separate worlds. + * Properties for recentlyAudible notification and muting of page. + * Content size and scroll position properties are now available. + * New API to print to PDF. + + - WebEngineProfile: + * New API for disabling or clearing HTTP cache + + - WebEngineSettings: + * New settings for controlling WebGL, automatic favicon download and more. + + +**************************************************************************** +* Qt WebEngineWidgets * +**************************************************************************** + + - QWebEngineContextMenuData: + * A new API exposing data useful for context menu generation. + + - QWebEnginePage: + * New WebAction for opening new tabs in background. + * New WebAction for saving page on disk in multiple different formats + including MHTML. + * Direct access to QIcon version of favicons. + * JavaScript can now be executed in separate worlds. + * WebChannels can now be installed in separate worlds. + * Signals for recentlyAudible notification and muting of page. + * Content size and scroll position properties are now available. + * New API to print to PDF. + + - QWebEngineProfile: + * New API for disabling or clearing HTTP cache + + - QWebEngineSettings: + * New settings for controlling WebGL, automatic favicon download and more. + +**************************************************************************** +* Examples * +**************************************************************************** + diff --git a/examples/webengine/quicknanobrowser/BrowserWindow.qml b/examples/webengine/quicknanobrowser/BrowserWindow.qml index b468b2a77..c008425d9 100644 --- a/examples/webengine/quicknanobrowser/BrowserWindow.qml +++ b/examples/webengine/quicknanobrowser/BrowserWindow.qml @@ -237,6 +237,7 @@ ApplicationWindow { z: 2 id: faviconImage width: 16; height: 16 + sourceSize: Qt.size(width, height) source: currentWebView && currentWebView.icon } style: TextFieldStyle { diff --git a/examples/webenginewidgets/demobrowser/browsermainwindow.cpp b/examples/webenginewidgets/demobrowser/browsermainwindow.cpp index 0f24de707..fbee934db 100644 --- a/examples/webenginewidgets/demobrowser/browsermainwindow.cpp +++ b/examples/webenginewidgets/demobrowser/browsermainwindow.cpp @@ -56,6 +56,7 @@ #include "chasewidget.h" #include "downloadmanager.h" #include "history.h" +#include "printtopdfdialog.h" #include "settings.h" #include "tabwidget.h" #include "toolbarsearch.h" @@ -313,9 +314,7 @@ void BrowserMainWindow::setupMenu() fileMenu->addAction(tr("P&rint Preview..."), this, SLOT(slotFilePrintPreview())); fileMenu->addAction(tr("&Print..."), this, SLOT(slotFilePrint()), QKeySequence::Print); #endif -#ifndef QT_NO_PRINTER fileMenu->addAction(tr("&Print to PDF..."), this, SLOT(slotFilePrintToPDF())); -#endif // ifndef QT_NO_PRINTER fileMenu->addSeparator(); QAction *action = fileMenu->addAction(tr("Private &Browsing..."), this, SLOT(slotPrivateBrowsing())); @@ -718,20 +717,17 @@ void BrowserMainWindow::slotHandlePdfPrinted(const QByteArray& result) void BrowserMainWindow::slotFilePrintToPDF() { -#ifndef QT_NO_PRINTER - if (!currentTab()) + if (!currentTab() || !m_printerOutputFileName.isEmpty()) return; - QPrinter printer; - QPrintDialog *dialog = new QPrintDialog(&printer, this); - dialog->setWindowTitle(tr("Print Document")); - if (dialog->exec() != QDialog::Accepted || printer.outputFileName().isEmpty() || !m_printerOutputFileName.isEmpty()) - return; - - m_printerOutputFileName = printer.outputFileName(); - currentTab()->page()->printToPdf(invoke(this, &BrowserMainWindow::slotHandlePdfPrinted), printer.pageLayout()); + QFileInfo info(QStringLiteral("printout.pdf")); + PrintToPdfDialog *dialog = new PrintToPdfDialog(info.absoluteFilePath(), this); + dialog->setWindowTitle(tr("Print to PDF")); + if (dialog->exec() != QDialog::Accepted || dialog->filePath().isEmpty()) + return; -#endif // QT_NO_PRINTER + m_printerOutputFileName = dialog->filePath(); + currentTab()->page()->printToPdf(invoke(this, &BrowserMainWindow::slotHandlePdfPrinted), dialog->pageLayout()); } #if defined(QWEBENGINEPAGE_PRINT) diff --git a/examples/webenginewidgets/demobrowser/demobrowser.pro b/examples/webenginewidgets/demobrowser/demobrowser.pro index e295cd9dd..87f362f90 100644 --- a/examples/webenginewidgets/demobrowser/demobrowser.pro +++ b/examples/webenginewidgets/demobrowser/demobrowser.pro @@ -15,6 +15,7 @@ FORMS += \ downloads.ui \ history.ui \ passworddialog.ui \ + printtopdfdialog.ui \ proxy.ui \ savepagedialog.ui \ settings.ui @@ -32,6 +33,7 @@ HEADERS += \ fullscreennotification.h \ history.h \ modelmenu.h \ + printtopdfdialog.h \ savepagedialog.h \ searchlineedit.h \ settings.h \ @@ -55,6 +57,7 @@ SOURCES += \ fullscreennotification.cpp \ history.cpp \ modelmenu.cpp \ + printtopdfdialog.cpp \ savepagedialog.cpp \ searchlineedit.cpp \ settings.cpp \ diff --git a/examples/webenginewidgets/demobrowser/history.cpp b/examples/webenginewidgets/demobrowser/history.cpp index 32100e543..aaab44ac8 100644 --- a/examples/webenginewidgets/demobrowser/history.cpp +++ b/examples/webenginewidgets/demobrowser/history.cpp @@ -226,9 +226,9 @@ void HistoryManager::clear() { m_history.clear(); m_lastSavedUrl = QString(); + emit historyReset(); m_saveTimer->changeOccurred(); m_saveTimer->saveIfNeccessary(); - historyReset(); } void HistoryManager::loadSettings() diff --git a/examples/webenginewidgets/demobrowser/printtopdfdialog.cpp b/examples/webenginewidgets/demobrowser/printtopdfdialog.cpp new file mode 100644 index 000000000..0f3b1765e --- /dev/null +++ b/examples/webenginewidgets/demobrowser/printtopdfdialog.cpp @@ -0,0 +1,132 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "printtopdfdialog.h" +#include "ui_printtopdfdialog.h" + +#include <QtCore/QDir> +#ifndef QT_NO_PRINTER +#include <QtPrintSupport/QPageSetupDialog> +#include <QtPrintSupport/QPrinter> +#endif // QT_NO_PRINTER +#include <QtWidgets/QFileDialog> + +PrintToPdfDialog::PrintToPdfDialog(const QString &filePath, QWidget *parent) : + QDialog(parent), + currentPageLayout(QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(0.0, 0.0, 0.0, 0.0))), + ui(new Ui::PrintToPdfDialog) +{ + ui->setupUi(this); + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + connect(ui->chooseFilePathButton, &QToolButton::clicked, this, &PrintToPdfDialog::onChooseFilePathButtonClicked); +#ifndef QT_NO_PRINTER + connect(ui->choosePageLayoutButton, &QToolButton::clicked, this, &PrintToPdfDialog::onChoosePageLayoutButtonClicked); +#else + ui->choosePageLayoutButton->hide(); +#endif // QT_NO_PRINTER + updatePageLayoutLabel(); + setFilePath(filePath); +} + +PrintToPdfDialog::~PrintToPdfDialog() +{ + delete ui; +} + +void PrintToPdfDialog::onChoosePageLayoutButtonClicked() +{ +#ifndef QT_NO_PRINTER + QPrinter printer; + printer.setPageLayout(currentPageLayout); + + QPageSetupDialog dlg(&printer, this); + if (dlg.exec() != QDialog::Accepted) + return; + currentPageLayout.setPageSize(printer.pageLayout().pageSize()); + currentPageLayout.setOrientation(printer.pageLayout().orientation()); + updatePageLayoutLabel(); +#endif // QT_NO_PRINTER +} + +void PrintToPdfDialog::onChooseFilePathButtonClicked() +{ + QFileInfo fi(filePath()); + QFileDialog dlg(this, tr("Save PDF as"), fi.absolutePath()); + dlg.setAcceptMode(QFileDialog::AcceptSave); + dlg.setDefaultSuffix(QStringLiteral(".pdf")); + dlg.selectFile(fi.absoluteFilePath()); + if (dlg.exec() != QDialog::Accepted) + return; + setFilePath(dlg.selectedFiles().first()); +} + +QString PrintToPdfDialog::filePath() const +{ + return QDir::fromNativeSeparators(ui->filePathLineEdit->text()); +} + +void PrintToPdfDialog::setFilePath(const QString &filePath) +{ + ui->filePathLineEdit->setText(QDir::toNativeSeparators(filePath)); +} + +QPageLayout PrintToPdfDialog::pageLayout() const +{ + return currentPageLayout; +} + +void PrintToPdfDialog::updatePageLayoutLabel() +{ + ui->pageLayoutLabel->setText(QString("%1, %2").arg( + currentPageLayout.pageSize().name()).arg( + currentPageLayout.orientation() == QPageLayout::Portrait + ? tr("Portrait") : tr("Landscape") + )); +} diff --git a/examples/webenginewidgets/demobrowser/printtopdfdialog.h b/examples/webenginewidgets/demobrowser/printtopdfdialog.h new file mode 100644 index 000000000..87fca72c3 --- /dev/null +++ b/examples/webenginewidgets/demobrowser/printtopdfdialog.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PRINTTOPDFDIALOG_H +#define PRINTTOPDFDIALOG_H + +#include <QDialog> +#include <QPageLayout> + +QT_BEGIN_NAMESPACE +namespace Ui { +class PrintToPdfDialog; +} +QT_END_NAMESPACE + +class PrintToPdfDialog : public QDialog +{ + Q_OBJECT + +public: + explicit PrintToPdfDialog(const QString &filePath, QWidget *parent = 0); + ~PrintToPdfDialog(); + + QString filePath() const; + QPageLayout pageLayout() const; + +private slots: + void onChoosePageLayoutButtonClicked(); + void onChooseFilePathButtonClicked(); + +private: + void setFilePath(const QString &); + void updatePageLayoutLabel(); + + QPageLayout currentPageLayout; + Ui::PrintToPdfDialog *ui; +}; + +#endif // PRINTTOPDFDIALOG_H diff --git a/examples/webenginewidgets/demobrowser/printtopdfdialog.ui b/examples/webenginewidgets/demobrowser/printtopdfdialog.ui new file mode 100644 index 000000000..dcfd5a3aa --- /dev/null +++ b/examples/webenginewidgets/demobrowser/printtopdfdialog.ui @@ -0,0 +1,119 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>PrintToPdfDialog</class> + <widget class="QDialog" name="PrintToPdfDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>372</width> + <height>117</height> + </rect> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="2" column="0"> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + <item row="0" column="0" colspan="2"> + <layout class="QGridLayout" name="gridLayout"> + <item row="1" column="3"> + <widget class="QToolButton" name="choosePageLayoutButton"> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="filePathLabel"> + <property name="text"> + <string>Save as:</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QLineEdit" name="filePathLineEdit"/> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="layoutLabel"> + <property name="text"> + <string>Page layout:</string> + </property> + </widget> + </item> + <item row="0" column="3"> + <widget class="QToolButton" name="chooseFilePathButton"> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QLabel" name="pageLayoutLabel"> + <property name="text"> + <string/> + </property> + </widget> + </item> + </layout> + </item> + <item row="1" column="0"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>PrintToPdfDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>PrintToPdfDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/examples/webenginewidgets/demobrowser/urllineedit.cpp b/examples/webenginewidgets/demobrowser/urllineedit.cpp index e56ab63a5..8203e4f0f 100644 --- a/examples/webenginewidgets/demobrowser/urllineedit.cpp +++ b/examples/webenginewidgets/demobrowser/urllineedit.cpp @@ -338,7 +338,7 @@ void UrlLineEdit::paintEvent(QPaintEvent *event) QColor loadingColor = QColor(116, 192, 250); painter.setBrush(generateGradient(loadingColor)); painter.setPen(Qt::transparent); - int mid = backgroundRect.width() / 100 * progress; + int mid = backgroundRect.width() / 100.0f * progress; QRect progressRect(backgroundRect.x(), backgroundRect.y(), mid, backgroundRect.height()); painter.drawRect(progressRect); } diff --git a/examples/webenginewidgets/demobrowser/webview.cpp b/examples/webenginewidgets/demobrowser/webview.cpp index 192df6836..633b72bf1 100644 --- a/examples/webenginewidgets/demobrowser/webview.cpp +++ b/examples/webenginewidgets/demobrowser/webview.cpp @@ -104,16 +104,6 @@ BrowserMainWindow *WebPage::mainWindow() return BrowserApplication::instance()->mainWindow(); } -bool WebPage::acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame) -{ - Q_UNUSED(type); - if (isMainFrame) { - m_loadingUrl = url; - emit loadingUrl(m_loadingUrl); - } - return true; -} - bool WebPage::certificateError(const QWebEngineCertificateError &error) { if (error.isOverridable()) { @@ -385,6 +375,7 @@ void WebView::contextMenuEvent(QContextMenuEvent *event) } if (page()->contextMenuData().selectedText().isEmpty()) menu->addAction(page()->action(QWebEnginePage::SavePage)); + connect(menu, &QMenu::aboutToHide, menu, &QObject::deleteLater); menu->popup(event->globalPos()); } diff --git a/examples/webenginewidgets/demobrowser/webview.h b/examples/webenginewidgets/demobrowser/webview.h index a931d3702..e3df8f795 100644 --- a/examples/webenginewidgets/demobrowser/webview.h +++ b/examples/webenginewidgets/demobrowser/webview.h @@ -65,16 +65,11 @@ QT_END_NAMESPACE class BrowserMainWindow; class WebPage : public QWebEnginePage { Q_OBJECT - -signals: - void loadingUrl(const QUrl &url); - public: WebPage(QWebEngineProfile *profile, QObject *parent = 0); BrowserMainWindow *mainWindow(); protected: - bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame) Q_DECL_OVERRIDE; QWebEnginePage *createWindow(QWebEnginePage::WebWindowType type) Q_DECL_OVERRIDE; #if !defined(QT_NO_UITOOLS) QObject *createPlugin(const QString &classId, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues); @@ -94,7 +89,6 @@ private: // set the webview mousepressedevent Qt::KeyboardModifiers m_keyboardModifiers; Qt::MouseButtons m_pressedButtons; - QUrl m_loadingUrl; }; class WebView : public QWebEngineView { diff --git a/examples/webenginewidgets/simplebrowser/browser.cpp b/examples/webenginewidgets/simplebrowser/browser.cpp index 78b60b8f8..f1420c2a3 100644 --- a/examples/webenginewidgets/simplebrowser/browser.cpp +++ b/examples/webenginewidgets/simplebrowser/browser.cpp @@ -42,20 +42,9 @@ #include "browserwindow.h" #include "webview.h" #include <QAuthenticator> -#include <QNetworkProxy> -#include <QNetworkReply> Browser::Browser() { - // QTBUG-47967 , downloading favIcon support is coming in 5.7 - QObject::connect(&WebView::networkAccessManager(), &QNetworkAccessManager::authenticationRequired, - [](QNetworkReply *, QAuthenticator *) { - qWarning("Authentication required for downloading favicon."); - }); - QObject::connect(&WebView::networkAccessManager(), &QNetworkAccessManager::proxyAuthenticationRequired, - [](const QNetworkProxy &, QAuthenticator *) { - qWarning("Proxy authentication required for downloading favicon."); - }); } Browser::~Browser() diff --git a/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc b/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc index b8df9b02a..e57ec80ec 100644 --- a/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc +++ b/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc @@ -123,7 +123,6 @@ functionality: \list - \li Downloading favicons \li Displaying error messages in case \c renderProcess dies \li Handling \c createWindow requests \li Adding custom menu items to context menus @@ -136,21 +135,11 @@ \printuntil WebView( \dots \skipto protected: - \printuntil handleIconLoaded + \printuntil webActionEnabledChanged \skipto } \dots \printline }; - \section2 Downloading Favicons - - To download a favicon, we use QNetworkAccessManager and create a - QNetworkRequest every time the URL specified by - QWebEngineView::iconUrlChanged is emitted: - - \quotefromfile webenginewidgets/simplebrowser/webview.cpp - \skipto WebView::handleIconUrlChanged( - \printuntil } - \section2 Displaying Error Messages If the render process is terminated, we display a QMessageBox with an error diff --git a/examples/webenginewidgets/simplebrowser/simplebrowser.pro b/examples/webenginewidgets/simplebrowser/simplebrowser.pro index ad8a9a2bd..197d68091 100644 --- a/examples/webenginewidgets/simplebrowser/simplebrowser.pro +++ b/examples/webenginewidgets/simplebrowser/simplebrowser.pro @@ -1,6 +1,6 @@ TEMPLATE = app TARGET = simplebrowser -QT += webenginewidgets network +QT += webenginewidgets CONFIG += c++11 HEADERS += \ diff --git a/examples/webenginewidgets/simplebrowser/tabwidget.cpp b/examples/webenginewidgets/simplebrowser/tabwidget.cpp index 3c6269f52..a7f855c2a 100644 --- a/examples/webenginewidgets/simplebrowser/tabwidget.cpp +++ b/examples/webenginewidgets/simplebrowser/tabwidget.cpp @@ -80,7 +80,11 @@ void TabWidget::handleCurrentChanged(int index) emit titleChanged(view->title()); emit loadProgress(view->loadProgress()); emit urlChanged(view->url()); - emit iconChanged(view->icon()); + QIcon pageIcon = view->page()->icon(); + if (!pageIcon.isNull()) + emit iconChanged(pageIcon); + else + emit iconChanged(QIcon(QStringLiteral(":defaulticon.png"))); emit webActionEnabledChanged(QWebEnginePage::Back, view->isWebActionEnabled(QWebEnginePage::Back)); emit webActionEnabledChanged(QWebEnginePage::Forward, view->isWebActionEnabled(QWebEnginePage::Forward)); emit webActionEnabledChanged(QWebEnginePage::Stop, view->isWebActionEnabled(QWebEnginePage::Stop)); @@ -89,7 +93,7 @@ void TabWidget::handleCurrentChanged(int index) emit titleChanged(QString()); emit loadProgress(0); emit urlChanged(QUrl()); - emit iconChanged(QIcon()); + emit iconChanged(QIcon(QStringLiteral(":defaulticon.png"))); emit webActionEnabledChanged(QWebEnginePage::Back, false); emit webActionEnabledChanged(QWebEnginePage::Forward, false); emit webActionEnabledChanged(QWebEnginePage::Stop, false); @@ -166,12 +170,14 @@ void TabWidget::setupView(WebView *webView) if (currentIndex() == indexOf(webView)) emit linkHovered(url); }); - connect(webView, &WebView::iconChanged, [this, webView](const QIcon& icon) { + connect(webPage, &WebPage::iconChanged, [this, webView](const QIcon &icon) { int index = indexOf(webView); + QIcon ico = icon.isNull() ? QIcon(QStringLiteral(":defaulticon.png")) : icon; + if (index != -1) - setTabIcon(index, icon); + setTabIcon(index, ico); if (currentIndex() == index) - emit iconChanged(icon); + emit iconChanged(ico); }); connect(webView, &WebView::webActionEnabledChanged, [this, webView](QWebEnginePage::WebAction action, bool enabled) { if (currentIndex() == indexOf(webView)) diff --git a/examples/webenginewidgets/simplebrowser/webpopupwindow.cpp b/examples/webenginewidgets/simplebrowser/webpopupwindow.cpp index a3175e546..8146dcfb7 100644 --- a/examples/webenginewidgets/simplebrowser/webpopupwindow.cpp +++ b/examples/webenginewidgets/simplebrowser/webpopupwindow.cpp @@ -65,7 +65,7 @@ WebPopupWindow::WebPopupWindow(QWebEngineProfile *profile) connect(m_view, &WebView::titleChanged, this, &QWidget::setWindowTitle); connect(m_view, &WebView::urlChanged, this, &WebPopupWindow::setUrl); - connect(m_view, &WebView::iconChanged, this, &WebPopupWindow::handleIconChanged); + connect(m_view->page(), &WebPage::iconChanged, this, &WebPopupWindow::handleIconChanged); connect(m_view->page(), &WebPage::geometryChangeRequested, this, &WebPopupWindow::handleGeometryChangeRequested); connect(m_view->page(), &WebPage::windowCloseRequested, this, &QWidget::close); } @@ -91,5 +91,8 @@ void WebPopupWindow::handleGeometryChangeRequested(const QRect &newGeometry) void WebPopupWindow::handleIconChanged(const QIcon &icon) { - m_addressBar->setFavIcon(icon); + if (icon.isNull()) + m_addressBar->setFavIcon(QIcon(QStringLiteral(":defaulticon.png"))); + else + m_addressBar->setFavIcon(icon); } diff --git a/examples/webenginewidgets/simplebrowser/webview.cpp b/examples/webenginewidgets/simplebrowser/webview.cpp index 559daca61..24835b10b 100644 --- a/examples/webenginewidgets/simplebrowser/webview.cpp +++ b/examples/webenginewidgets/simplebrowser/webview.cpp @@ -47,7 +47,6 @@ #include <QContextMenuEvent> #include <QMenu> #include <QMessageBox> -#include <QNetworkReply> #include <QTimer> WebView::WebView(QWidget *parent) @@ -59,11 +58,10 @@ WebView::WebView(QWidget *parent) }); connect(this, &QWebEngineView::loadFinished, [this](bool success) { if (!success) { - qWarning() << "Could not load page: " << url(); m_loadProgress = 0; } }); - connect(this, &QWebEngineView::iconUrlChanged, this, &WebView::handleIconUrlChanged); + connect(this, &QWebEngineView::renderProcessTerminated, [this](QWebEnginePage::RenderProcessTerminationStatus termStatus, int statusCode) { QString status; @@ -95,13 +93,6 @@ void WebView::setPage(WebPage *page) QWebEngineView::setPage(page); } -QIcon WebView::icon() const -{ - if (!m_icon.isNull()) - return m_icon; - return QIcon(QLatin1String(":defaulticon.png")); -} - int WebView::loadProgress() const { return m_loadProgress; @@ -120,12 +111,6 @@ bool WebView::isWebActionEnabled(QWebEnginePage::WebAction webAction) const return page()->action(webAction)->isEnabled(); } -QNetworkAccessManager &WebView::networkAccessManager() -{ - static QNetworkAccessManager networkAccessManager; - return networkAccessManager; -} - QWebEngineView *WebView::createWindow(QWebEnginePage::WebWindowType type) { switch (type) { @@ -158,36 +143,11 @@ void WebView::contextMenuEvent(QContextMenuEvent *event) if (it != actions.cend()) { (*it)->setText(tr("Open Link in This Tab")); ++it; - menu->insertAction(*it, page()->action(QWebEnginePage::OpenLinkInNewWindow)); - menu->insertAction(*it, page()->action(QWebEnginePage::OpenLinkInNewTab)); + QAction *before(it == actions.cend() ? nullptr : *it); + menu->insertAction(before, page()->action(QWebEnginePage::OpenLinkInNewWindow)); + menu->insertAction(before, page()->action(QWebEnginePage::OpenLinkInNewTab)); } + connect(menu, &QMenu::aboutToHide, menu, &QObject::deleteLater); menu->popup(event->globalPos()); } -void WebView::handleIconUrlChanged(const QUrl &url) -{ - QNetworkRequest iconRequest(url); -#ifndef QT_NO_OPENSSL - QSslConfiguration conf = iconRequest.sslConfiguration(); - conf.setPeerVerifyMode(QSslSocket::VerifyNone); - iconRequest.setSslConfiguration(conf); -#endif - QNetworkReply *iconReply = networkAccessManager().get(iconRequest); - iconReply->setParent(this); - connect(iconReply, &QNetworkReply::finished, this, &WebView::handleIconLoaded); -} - -void WebView::handleIconLoaded() -{ - QNetworkReply *iconReply = qobject_cast<QNetworkReply*>(sender()); - if (iconReply && iconReply->error() == QNetworkReply::NoError) { - QByteArray data = iconReply->readAll(); - QPixmap pixmap; - pixmap.loadFromData(data); - m_icon.addPixmap(pixmap); - iconReply->deleteLater(); - } else { - m_icon = QIcon(QStringLiteral(":defaulticon.png")); - } - emit iconChanged(m_icon); -} diff --git a/examples/webenginewidgets/simplebrowser/webview.h b/examples/webenginewidgets/simplebrowser/webview.h index 5450ee247..f06162ea3 100644 --- a/examples/webenginewidgets/simplebrowser/webview.h +++ b/examples/webenginewidgets/simplebrowser/webview.h @@ -54,29 +54,21 @@ public: WebView(QWidget *parent = nullptr); void setPage(WebPage *page); - QIcon icon() const; int loadProgress() const; bool isWebActionEnabled(QWebEnginePage::WebAction webAction) const; - static QNetworkAccessManager &networkAccessManager(); protected: void contextMenuEvent(QContextMenuEvent *event) override; QWebEngineView *createWindow(QWebEnginePage::WebWindowType type) override; signals: - void iconChanged(const QIcon &icon); void webActionEnabledChanged(QWebEnginePage::WebAction webAction, bool enabled); -private slots: - void handleIconUrlChanged(const QUrl &url); - void handleIconLoaded(); - private: void createWebActionTrigger(QWebEnginePage *page, QWebEnginePage::WebAction); private: int m_loadProgress; - QIcon m_icon; }; #endif diff --git a/src/3rdparty b/src/3rdparty -Subproject 349c3122be9f932991f938a33e761b00062a5f5 +Subproject ba40ed24a6d23e606397b650a7982b0998dbeaf diff --git a/src/core/api/qtwebenginecoreglobal.cpp b/src/core/api/qtwebenginecoreglobal.cpp index 116f39c68..8f004777f 100644 --- a/src/core/api/qtwebenginecoreglobal.cpp +++ b/src/core/api/qtwebenginecoreglobal.cpp @@ -78,6 +78,11 @@ QWEBENGINE_PRIVATE_EXPORT void initialize() qFatal("QtWebEngine::initialize() must be called after the construction of the application object."); return; } + + // Bail out silently if the user did not construct a QGuiApplication. + if (!qobject_cast<QGuiApplication *>(app)) + return; + if (app->thread() != QThread::currentThread()) { qFatal("QtWebEngine::initialize() must be called from the Qt gui thread."); return; diff --git a/src/core/api/qwebengineurlrequestinfo.h b/src/core/api/qwebengineurlrequestinfo.h index 34570b61f..d75ceabf6 100644 --- a/src/core/api/qwebengineurlrequestinfo.h +++ b/src/core/api/qwebengineurlrequestinfo.h @@ -73,8 +73,8 @@ public: ResourceTypeXhr, // a XMLHttpRequest ResourceTypePing, // a ping request for <a ping> ResourceTypeServiceWorker, // the main resource of a service worker. - ResourceTypeCspReport, - ResourceTypePluginResource, + ResourceTypeCspReport, // Content Security Policy (CSP) violation report + ResourceTypePluginResource, // A resource requested by a plugin ResourceTypeUnknown }; diff --git a/src/core/browser_context_adapter.cpp b/src/core/browser_context_adapter.cpp index 193c49e34..e0f933562 100644 --- a/src/core/browser_context_adapter.cpp +++ b/src/core/browser_context_adapter.cpp @@ -168,7 +168,7 @@ void BrowserContextAdapter::cancelDownload(quint32 downloadId) downloadManagerDelegate()->cancelDownload(downloadId); } -BrowserContextAdapter* BrowserContextAdapter::defaultContext() +QSharedPointer<BrowserContextAdapter> BrowserContextAdapter::defaultContext() { return WebEngineContext::current()->defaultBrowserContext(); } @@ -354,11 +354,16 @@ void BrowserContextAdapter::setHttpCacheMaxSize(int maxSize) m_browserContext->url_request_getter_->updateHttpCache(); } -QHash<QByteArray, QWebEngineUrlSchemeHandler *> &BrowserContextAdapter::customUrlSchemeHandlers() +const QHash<QByteArray, QWebEngineUrlSchemeHandler *> &BrowserContextAdapter::customUrlSchemeHandlers() const { return m_customUrlSchemeHandlers; } +const QList<QByteArray> BrowserContextAdapter::customUrlSchemes() const +{ + return m_customUrlSchemeHandlers.keys(); +} + void BrowserContextAdapter::updateCustomUrlSchemeHandlers() { if (m_browserContext->url_request_getter_.get()) @@ -396,6 +401,12 @@ void BrowserContextAdapter::addCustomUrlSchemeHandler(const QByteArray &scheme, updateCustomUrlSchemeHandlers(); } +void BrowserContextAdapter::clearCustomUrlSchemeHandlers() +{ + m_customUrlSchemeHandlers.clear(); + updateCustomUrlSchemeHandlers(); +} + UserResourceControllerHost *BrowserContextAdapter::userResourceController() { if (!m_userResourceController) @@ -432,7 +443,21 @@ QString BrowserContextAdapter::httpAcceptLanguage() const void BrowserContextAdapter::setHttpAcceptLanguage(const QString &httpAcceptLanguage) { + if (m_httpAcceptLanguage == httpAcceptLanguage) + return; m_httpAcceptLanguage = httpAcceptLanguage; + + std::vector<content::WebContentsImpl *> list = content::WebContentsImpl::GetAllWebContents(); + Q_FOREACH (content::WebContentsImpl *web_contents, list) { + if (web_contents->GetBrowserContext() == m_browserContext.data()) { + content::RendererPreferences* rendererPrefs = web_contents->GetMutableRendererPrefs(); + rendererPrefs->accept_languages = httpAcceptLanguageWithoutQualities().toStdString(); + web_contents->GetRenderViewHost()->SyncRendererPrefs(); + } + } + + if (m_browserContext->url_request_getter_.get()) + m_browserContext->url_request_getter_->updateUserAgent(); } void BrowserContextAdapter::clearHttpCache() diff --git a/src/core/browser_context_adapter.h b/src/core/browser_context_adapter.h index 3e1e6389c..c3c3f153d 100644 --- a/src/core/browser_context_adapter.h +++ b/src/core/browser_context_adapter.h @@ -42,10 +42,10 @@ #include "qtwebenginecoreglobal.h" +#include <QEnableSharedFromThis> #include <QList> #include <QPointer> #include <QScopedPointer> -#include <QSharedData> #include <QString> #include <QVector> @@ -63,14 +63,14 @@ class DownloadManagerDelegateQt; class UserResourceControllerHost; class WebEngineVisitedLinksManager; -class QWEBENGINE_EXPORT BrowserContextAdapter : public QSharedData +class QWEBENGINE_EXPORT BrowserContextAdapter : public QEnableSharedFromThis<BrowserContextAdapter> { public: explicit BrowserContextAdapter(bool offTheRecord = false); explicit BrowserContextAdapter(const QString &storagePrefix); virtual ~BrowserContextAdapter(); - static BrowserContextAdapter* defaultContext(); + static QSharedPointer<BrowserContextAdapter> defaultContext(); static QObject* globalQObjectRoot(); WebEngineVisitedLinksManager *visitedLinksManager(); @@ -156,8 +156,9 @@ public: bool trackVisitedLinks() const; bool persistVisitedLinks() const; - QHash<QByteArray, QWebEngineUrlSchemeHandler *> &customUrlSchemeHandlers(); - void updateCustomUrlSchemeHandlers(); + const QHash<QByteArray, QWebEngineUrlSchemeHandler *> &customUrlSchemeHandlers() const; + const QList<QByteArray> customUrlSchemes() const; + void clearCustomUrlSchemeHandlers(); void addCustomUrlSchemeHandler(const QByteArray &, QWebEngineUrlSchemeHandler *); bool removeCustomUrlSchemeHandler(QWebEngineUrlSchemeHandler *); QWebEngineUrlSchemeHandler *takeCustomUrlSchemeHandler(const QByteArray &); @@ -173,6 +174,8 @@ public: void clearHttpCache(); private: + void updateCustomUrlSchemeHandlers(); + QString m_name; bool m_offTheRecord; QScopedPointer<BrowserContextQt> m_browserContext; diff --git a/src/core/browser_context_qt.cpp b/src/core/browser_context_qt.cpp index dc337493e..5b3115530 100644 --- a/src/core/browser_context_qt.cpp +++ b/src/core/browser_context_qt.cpp @@ -174,7 +174,7 @@ content::PushMessagingService *BrowserContextQt::GetPushMessagingService() content::SSLHostStateDelegate* BrowserContextQt::GetSSLHostStateDelegate() { if (!sslHostStateDelegate) - sslHostStateDelegate.reset(new SSLHostStateDelegateQt(m_adapter)); + sslHostStateDelegate.reset(new SSLHostStateDelegateQt()); return sslHostStateDelegate.get(); } @@ -191,13 +191,13 @@ content::BackgroundSyncController* BrowserContextQt::GetBackgroundSyncController content::PermissionManager *BrowserContextQt::GetPermissionManager() { if (!permissionManager) - permissionManager.reset(new PermissionManagerQt(m_adapter)); + permissionManager.reset(new PermissionManagerQt()); return permissionManager.get(); } net::URLRequestContextGetter *BrowserContextQt::CreateRequestContext(content::ProtocolHandlerMap *protocol_handlers, content::URLRequestInterceptorScopedVector request_interceptors) { - url_request_getter_ = new URLRequestContextGetterQt(m_adapter, protocol_handlers, std::move(request_interceptors)); + url_request_getter_ = new URLRequestContextGetterQt(m_adapter->sharedFromThis(), protocol_handlers, std::move(request_interceptors)); return url_request_getter_.get(); } diff --git a/src/core/browser_message_filter_qt.cpp b/src/core/browser_message_filter_qt.cpp index 2f4c5056f..7551e5616 100644 --- a/src/core/browser_message_filter_qt.cpp +++ b/src/core/browser_message_filter_qt.cpp @@ -50,6 +50,11 @@ BrowserMessageFilterQt::BrowserMessageFilterQt(int /*render_process_id*/) { } +// The following is based on chrome/browser/plugins/plugin_info_message_filter.cc: +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + bool BrowserMessageFilterQt::OnMessageReceived(const IPC::Message& message) { IPC_BEGIN_MESSAGE_MAP(BrowserMessageFilterQt, message) diff --git a/src/core/chrome_qt.gyp b/src/core/chrome_qt.gyp index d7e6cc2e9..f2d7c5831 100644 --- a/src/core/chrome_qt.gyp +++ b/src/core/chrome_qt.gyp @@ -132,8 +132,6 @@ '<(DEPTH)/chrome/browser/printing/print_job_worker_owner.h', '<(DEPTH)/chrome/browser/printing/printer_query.cc', '<(DEPTH)/chrome/browser/printing/printer_query.h', - '<(DEPTH)/extensions/browser/notification_types.h', - '<(DEPTH)/extensions/browser/notification_types.cc', ], 'dependencies': [ '<(chromium_src_dir)/third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', diff --git a/src/core/clipboard_qt.cpp b/src/core/clipboard_qt.cpp index 3b3248559..cd57995ea 100644 --- a/src/core/clipboard_qt.cpp +++ b/src/core/clipboard_qt.cpp @@ -243,8 +243,7 @@ void ClipboardQt::WriteWebSmartPaste() void ClipboardQt::WriteBitmap(const SkBitmap& bitmap) { - QImage image(reinterpret_cast<const uchar *>(bitmap.getPixels()), bitmap.width(), bitmap.height(), QImage::Format_ARGB32); - getUncommittedData()->setImageData(image.copy()); + getUncommittedData()->setImageData(toQImage(bitmap).copy()); } void ClipboardQt::WriteBookmark(const char* title_data, size_t title_len, const char* url_data, size_t url_len) diff --git a/src/core/config/common.pri b/src/core/config/common.pri index 96506cd37..5822bc589 100644 --- a/src/core/config/common.pri +++ b/src/core/config/common.pri @@ -8,3 +8,5 @@ GYP_CONFIG += v8_use_external_startup_data=0 GYP_CONFIG += enable_basic_printing=1 enable_print_preview=0 # WebSpeech requires Google API keys and adds dependencies on speex and flac. GYP_CONFIG += enable_web_speech=0 +# We do not use or even include the extensions +GYP_CONFIG += enable_extensions=0 diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp index 7fc6556fb..8a5dde70f 100644 --- a/src/core/content_client_qt.cpp +++ b/src/core/content_client_qt.cpp @@ -58,6 +58,12 @@ #include <QString> #if defined(ENABLE_PLUGINS) + +// The plugin logic is based on chrome/common/chrome_content_client.cc: +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + #include "content/public/common/pepper_plugin_info.h" #include "ppapi/shared_impl/ppapi_permissions.h" @@ -95,7 +101,6 @@ static QString ppapiPluginsPath() } -// Adopted from chrome_content_client.cc content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path, const std::string& version) { content::PepperPluginInfo plugin; @@ -184,6 +189,17 @@ void AddPepperWidevine(std::vector<content::PepperPluginInfo>* plugins) pluginPaths << QtWebEngineCore::toQt(widevine_argument); else { pluginPaths << ppapiPluginsPath() + QStringLiteral("/") + QString::fromLatin1(kWidevineCdmAdapterFileName); +#if defined(Q_OS_OSX) + QDir potentialWidevineDir(QDir::homePath() + "/Library/Application Support/Google/Chrome/WidevineCDM"); + if (potentialWidevineDir.exists()) { + QFileInfoList widevineVersionDirs = potentialWidevineDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); + for (int i = 0; i < widevineVersionDirs.size(); ++i) { + QString versionDirPath(widevineVersionDirs.at(i).absoluteFilePath()); + QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/mac_x64/" + QString::fromLatin1(kWidevineCdmAdapterFileName); + pluginPaths << potentialWidevinePluginPath; + } + } +#endif #if defined(Q_OS_LINUX) pluginPaths << QStringLiteral("/opt/google/chrome/libwidevinecdmadapter.so") // Google Chrome << QStringLiteral("/usr/lib/chromium/libwidevinecdmadapter.so"); // Arch diff --git a/src/core/content_main_delegate_qt.cpp b/src/core/content_main_delegate_qt.cpp index ee52dd23e..5933f873b 100644 --- a/src/core/content_main_delegate_qt.cpp +++ b/src/core/content_main_delegate_qt.cpp @@ -71,6 +71,30 @@ static base::StringPiece PlatformResourceProvider(int key) { return base::StringPiece(); } +// Logging logic is based on chrome/common/logging_chrome.cc: +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +static logging::LoggingDestination DetermineLogMode(const base::CommandLine& command_line) +{ +#ifdef NDEBUG + bool enable_logging = false; + const char *kInvertLoggingSwitch = switches::kEnableLogging; +#else + bool enable_logging = true; + const char *kInvertLoggingSwitch = switches::kDisableLogging; +#endif + + if (command_line.HasSwitch(kInvertLoggingSwitch)) + enable_logging = !enable_logging; + + if (enable_logging) + return logging::LOG_TO_SYSTEM_DEBUG_LOG; + else + return logging::LOG_NONE; +} + void ContentMainDelegateQt::PreSandboxStartup() { #if defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX)) @@ -82,18 +106,19 @@ void ContentMainDelegateQt::PreSandboxStartup() net::NetModule::SetResourceProvider(PlatformResourceProvider); ui::ResourceBundle::InitSharedInstanceWithLocale(WebEngineLibraryInfo::getApplicationLocale(), 0, ui::ResourceBundle::LOAD_COMMON_RESOURCES); - // Suppress info, warning and error messages per default. - int logLevel = logging::LOG_FATAL; - base::CommandLine* parsedCommandLine = base::CommandLine::ForCurrentProcess(); - if (parsedCommandLine->HasSwitch(switches::kLoggingLevel)) { - std::string logLevelValue = parsedCommandLine->GetSwitchValueASCII(switches::kLoggingLevel); - int level = 0; - if (base::StringToInt(logLevelValue, &level) && level >= logging::LOG_INFO && level < logging::LOG_NUM_SEVERITIES) - logLevel = level; + logging::LoggingSettings settings; + settings.logging_dest = DetermineLogMode(*parsedCommandLine); + logging::InitLogging(settings); + + if (logging::GetMinLogLevel() >= logging::LOG_INFO) { + if (parsedCommandLine->HasSwitch(switches::kLoggingLevel)) { + std::string logLevelValue = parsedCommandLine->GetSwitchValueASCII(switches::kLoggingLevel); + int level = 0; + if (base::StringToInt(logLevelValue, &level) && level >= logging::LOG_INFO && level < logging::LOG_NUM_SEVERITIES) + logging::SetMinLogLevel(level); + } } - - logging::SetMinLogLevel(logLevel); } content::ContentBrowserClient *ContentMainDelegateQt::CreateContentBrowserClient() diff --git a/src/core/core_gyp_generator.pro b/src/core/core_gyp_generator.pro index 639470a32..09df6b48d 100644 --- a/src/core/core_gyp_generator.pro +++ b/src/core/core_gyp_generator.pro @@ -76,6 +76,7 @@ SOURCES = \ renderer/pepper/pepper_flash_browser_host_qt.cpp \ renderer/pepper/pepper_flash_renderer_host_qt.cpp \ renderer/pepper/pepper_host_factory_qt.cpp \ + renderer/pepper/pepper_isolated_file_system_message_filter.cpp \ renderer/pepper/pepper_renderer_host_factory_qt.cpp \ renderer/render_frame_observer_qt.cpp \ renderer/render_view_observer_qt.cpp \ @@ -157,6 +158,7 @@ HEADERS = \ renderer/pepper/pepper_flash_browser_host_qt.h \ renderer/pepper/pepper_flash_renderer_host_qt.h \ renderer/pepper/pepper_host_factory_qt.h \ + renderer/pepper/pepper_isolated_file_system_message_filter.h \ renderer/pepper/pepper_renderer_host_factory_qt.h \ renderer/render_frame_observer_qt.h \ renderer/render_view_observer_qt.h \ diff --git a/src/core/custom_protocol_handler.cpp b/src/core/custom_protocol_handler.cpp index 15eb82db1..402df04ba 100644 --- a/src/core/custom_protocol_handler.cpp +++ b/src/core/custom_protocol_handler.cpp @@ -46,8 +46,8 @@ namespace QtWebEngineCore { -CustomProtocolHandler::CustomProtocolHandler(QWebEngineUrlSchemeHandler *schemeHandler) - : m_schemeHandler(schemeHandler) +CustomProtocolHandler::CustomProtocolHandler(QWeakPointer<const BrowserContextAdapter> adapter) + : m_adapter(adapter) { } @@ -56,7 +56,7 @@ net::URLRequestJob *CustomProtocolHandler::MaybeCreateJob(net::URLRequest *reque if (!networkDelegate) return new net::URLRequestErrorJob(request, Q_NULLPTR, net::ERR_ACCESS_DENIED); - return new URLRequestCustomJob(request, networkDelegate, m_schemeHandler); + return new URLRequestCustomJob(request, networkDelegate, request->url().scheme(), m_adapter); } } // namespace diff --git a/src/core/custom_protocol_handler.h b/src/core/custom_protocol_handler.h index c56a983f8..38e17ffaf 100644 --- a/src/core/custom_protocol_handler.h +++ b/src/core/custom_protocol_handler.h @@ -45,10 +45,9 @@ #include <QtCore/QByteArray> #include <QtCore/QObject> -#include <QtCore/qcompilerdetection.h> // Needed for Q_DECL_OVERRIDE +#include <QtCore/QWeakPointer> QT_FORWARD_DECLARE_CLASS(QIODevice) -QT_FORWARD_DECLARE_CLASS(QWebEngineUrlSchemeHandler) namespace net { class NetworkDelegate; @@ -64,13 +63,13 @@ class BrowserContextAdapter; class QWEBENGINE_EXPORT CustomProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler { public: - CustomProtocolHandler(QWebEngineUrlSchemeHandler *); + CustomProtocolHandler(QWeakPointer<const BrowserContextAdapter> adapter); virtual net::URLRequestJob *MaybeCreateJob(net::URLRequest *request, net::NetworkDelegate *networkDelegate) const Q_DECL_OVERRIDE; private: DISALLOW_COPY_AND_ASSIGN(CustomProtocolHandler); - QWebEngineUrlSchemeHandler *m_schemeHandler; + QWeakPointer<const BrowserContextAdapter> m_adapter; }; } // namespace diff --git a/src/core/favicon_manager.cpp b/src/core/favicon_manager.cpp index 16a087efc..5568e6eb5 100644 --- a/src/core/favicon_manager.cpp +++ b/src/core/favicon_manager.cpp @@ -220,11 +220,15 @@ FaviconManager::~FaviconManager() QIcon FaviconManager::getIcon(const QUrl &url) const { Q_D(const FaviconManager); + if (!d->m_icons.contains(url)) + return QIcon(); + return d->m_icons[url]; } FaviconInfo FaviconManager::getFaviconInfo(const QUrl &url) const { + Q_ASSERT(m_faviconInfoMap.contains(url)); return m_faviconInfoMap[url]; } diff --git a/src/core/media_capture_devices_dispatcher.cpp b/src/core/media_capture_devices_dispatcher.cpp index 4d11277b0..b38e90c69 100644 --- a/src/core/media_capture_devices_dispatcher.cpp +++ b/src/core/media_capture_devices_dispatcher.cpp @@ -88,6 +88,7 @@ base::string16 getContentsUrl(content::WebContents *webContents) return base::UTF8ToUTF16(webContents->GetURL().GetOrigin().spec()); } +// Based on chrome/browser/media/desktop_capture_access_handler.cc: scoped_ptr<content::MediaStreamUI> getDevicesForDesktopCapture(content::MediaStreamDevices &devices, content::DesktopMediaID mediaId , bool captureAudio, bool /*display_notification*/, base::string16 /*application_title*/) { diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp index fd57ad7b8..36ce476cd 100644 --- a/src/core/permission_manager_qt.cpp +++ b/src/core/permission_manager_qt.cpp @@ -69,9 +69,8 @@ BrowserContextAdapter::PermissionType toQt(content::PermissionType type) return BrowserContextAdapter::UnsupportedPermission; } -PermissionManagerQt::PermissionManagerQt(BrowserContextAdapter *contextAdapter) - : m_contextAdapter(contextAdapter) - , m_requestIdCount(0) +PermissionManagerQt::PermissionManagerQt() + : m_requestIdCount(0) , m_subscriberIdCount(0) { } diff --git a/src/core/permission_manager_qt.h b/src/core/permission_manager_qt.h index 928f11c65..ff35357d8 100644 --- a/src/core/permission_manager_qt.h +++ b/src/core/permission_manager_qt.h @@ -52,7 +52,7 @@ namespace QtWebEngineCore { class PermissionManagerQt : public content::PermissionManager { public: - PermissionManagerQt(BrowserContextAdapter *); + PermissionManagerQt(); ~PermissionManagerQt(); typedef BrowserContextAdapter::PermissionType PermissionType; @@ -101,7 +101,6 @@ public: void UnsubscribePermissionStatusChange(int subscription_id) override; private: - BrowserContextAdapter *m_contextAdapter; QHash<QPair<QUrl, PermissionType>, bool> m_permissions; struct RequestOrSubscription { PermissionType type; diff --git a/src/core/print_view_manager_base_qt.cpp b/src/core/print_view_manager_base_qt.cpp index 60f166423..3e12901b9 100644 --- a/src/core/print_view_manager_base_qt.cpp +++ b/src/core/print_view_manager_base_qt.cpp @@ -34,6 +34,7 @@ ** ****************************************************************************/ +// This is based on chrome/browser/printing/print_view_manager_base.cc: // Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. diff --git a/src/core/printing_message_filter_qt.cpp b/src/core/printing_message_filter_qt.cpp index fd6dc0fc2..ba4d5c6e6 100644 --- a/src/core/printing_message_filter_qt.cpp +++ b/src/core/printing_message_filter_qt.cpp @@ -34,6 +34,7 @@ ** ****************************************************************************/ +// Based on chrome/browser/printing/printing_message_filter.cc: // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp index f3ac0f7ca..6094be847 100644 --- a/src/core/renderer/content_renderer_client_qt.cpp +++ b/src/core/renderer/content_renderer_client_qt.cpp @@ -202,6 +202,11 @@ bool ContentRendererClientQt::IsLinkVisited(unsigned long long linkHash) return m_visitedLinkSlave->IsVisited(linkHash); } +// The following is based on chrome/renderer/media/chrome_key_systems.cc: +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + #if defined(ENABLE_PEPPER_CDMS) static bool IsPepperCdmAvailable(const std::string& pepper_type, std::vector<base::string16>* additional_param_names, diff --git a/src/core/renderer/pepper/pepper_flash_browser_host_qt.cpp b/src/core/renderer/pepper/pepper_flash_browser_host_qt.cpp index ced7df065..4427a67f2 100644 --- a/src/core/renderer/pepper/pepper_flash_browser_host_qt.cpp +++ b/src/core/renderer/pepper/pepper_flash_browser_host_qt.cpp @@ -37,6 +37,7 @@ ** ****************************************************************************/ +// This is based on chrome/browser/renderer_host/pepper/pepper_flash_browser_host.cc: // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -70,7 +71,6 @@ using content::RenderProcessHost; namespace QtWebEngineCore { - PepperFlashBrowserHostQt::PepperFlashBrowserHostQt(BrowserPpapiHost* host, PP_Instance instance, PP_Resource resource) diff --git a/src/core/renderer/pepper/pepper_flash_renderer_host_qt.cpp b/src/core/renderer/pepper/pepper_flash_renderer_host_qt.cpp index 40d449b23..37ce4b5f3 100644 --- a/src/core/renderer/pepper/pepper_flash_renderer_host_qt.cpp +++ b/src/core/renderer/pepper/pepper_flash_renderer_host_qt.cpp @@ -37,6 +37,7 @@ ** ****************************************************************************/ +// This is based on chrome/renderer/pepper/pepper_flash_renderer_host.cc: // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. diff --git a/src/core/renderer/pepper/pepper_host_factory_qt.cpp b/src/core/renderer/pepper/pepper_host_factory_qt.cpp index 3ae5c8ff3..9fbd413ef 100644 --- a/src/core/renderer/pepper/pepper_host_factory_qt.cpp +++ b/src/core/renderer/pepper/pepper_host_factory_qt.cpp @@ -37,6 +37,11 @@ ** ****************************************************************************/ +// This is based on chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.cc: +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + #include "pepper_host_factory_qt.h" #include "build/build_config.h" @@ -46,7 +51,9 @@ #include "ppapi/host/resource_host.h" #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/shared_impl/ppapi_permissions.h" + #include "pepper_flash_browser_host_qt.h" +#include "pepper_isolated_file_system_message_filter.h" using ppapi::host::MessageFilterHost; using ppapi::host::ResourceHost; @@ -79,6 +86,19 @@ scoped_ptr<ppapi::host::ResourceHost> PepperHostFactoryQt::CreateResourceHost(pp instance, resource)); + // Permissions for the following interfaces will be checked at the + // time of the corresponding instance's methods calls (because + // permission check can be performed only on the UI + // thread). Currently these interfaces are available only for + // whitelisted apps which may not have access to the other private + // interfaces. + if (message.type() == PpapiHostMsg_IsolatedFileSystem_Create::ID) { + PepperIsolatedFileSystemMessageFilter* isolated_fs_filter = PepperIsolatedFileSystemMessageFilter::Create(instance, host_); + if (!isolated_fs_filter) + return scoped_ptr<ResourceHost>(); + return scoped_ptr<ResourceHost>(new MessageFilterHost(host, instance, resource, isolated_fs_filter)); + } + return scoped_ptr<ppapi::host::ResourceHost>(); } diff --git a/src/core/renderer/pepper/pepper_isolated_file_system_message_filter.cpp b/src/core/renderer/pepper/pepper_isolated_file_system_message_filter.cpp new file mode 100644 index 000000000..7e8b2fdda --- /dev/null +++ b/src/core/renderer/pepper/pepper_isolated_file_system_message_filter.cpp @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// This is based on chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.cc: +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "pepper_isolated_file_system_message_filter.h" + +#include "base/macros.h" +#include "chrome/common/chrome_switches.h" +#include "content/public/browser/browser_ppapi_host.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/child_process_security_policy.h" +#include "content/public/browser/render_view_host.h" +#include "ppapi/c/pp_errors.h" +#include "ppapi/host/dispatch_host_message.h" +#include "ppapi/host/host_message_context.h" +#include "ppapi/host/ppapi_host.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/shared_impl/file_system_util.h" +#include "storage/browser/fileapi/isolated_context.h" + +namespace QtWebEngineCore { + +// static +PepperIsolatedFileSystemMessageFilter* PepperIsolatedFileSystemMessageFilter::Create(PP_Instance instance, content::BrowserPpapiHost *host) +{ + int render_process_id; + int unused_render_frame_id; + if (!host->GetRenderFrameIDsForInstance(instance, &render_process_id, &unused_render_frame_id)) + return nullptr; + return new PepperIsolatedFileSystemMessageFilter(render_process_id, host->GetPpapiHost()); +} + +PepperIsolatedFileSystemMessageFilter::PepperIsolatedFileSystemMessageFilter(int render_process_id, + ppapi::host::PpapiHost *ppapi_host) + : m_render_process_id(render_process_id), + m_ppapi_host(ppapi_host) +{} + +PepperIsolatedFileSystemMessageFilter::~PepperIsolatedFileSystemMessageFilter() +{} + +scoped_refptr<base::TaskRunner> PepperIsolatedFileSystemMessageFilter::OverrideTaskRunnerForMessage(const IPC::Message &) +{ + // In order to reach ExtensionSystem, we need to get ProfileManager first. + // ProfileManager lives in UI thread, so we need to do this in UI thread. + return content::BrowserThread::GetMessageLoopProxyForThread(content::BrowserThread::UI); +} + +int32_t PepperIsolatedFileSystemMessageFilter::OnResourceMessageReceived(const IPC::Message& msg, ppapi::host::HostMessageContext *context) +{ + PPAPI_BEGIN_MESSAGE_MAP(PepperIsolatedFileSystemMessageFilter, msg) + PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_IsolatedFileSystem_BrowserOpen, OnOpenFileSystem) + PPAPI_END_MESSAGE_MAP() + return PP_ERROR_FAILED; +} + +int32_t PepperIsolatedFileSystemMessageFilter::OnOpenFileSystem(ppapi::host::HostMessageContext *context, + PP_IsolatedFileSystemType_Private type) +{ + switch (type) { + case PP_ISOLATEDFILESYSTEMTYPE_PRIVATE_INVALID: + break; + case PP_ISOLATEDFILESYSTEMTYPE_PRIVATE_CRX: + return PP_ERROR_NOTSUPPORTED; + case PP_ISOLATEDFILESYSTEMTYPE_PRIVATE_PLUGINPRIVATE: + return OpenPluginPrivateFileSystem(context); + } + NOTREACHED(); + context->reply_msg = PpapiPluginMsg_IsolatedFileSystem_BrowserOpenReply(std::string()); + return PP_ERROR_FAILED; +} + +int32_t PepperIsolatedFileSystemMessageFilter::OpenPluginPrivateFileSystem(ppapi::host::HostMessageContext *context) +{ + DCHECK(m_ppapi_host); + // Only plugins with private permission can open the filesystem. + if (!m_ppapi_host->permissions().HasPermission(ppapi::PERMISSION_PRIVATE)) + return PP_ERROR_NOACCESS; + + const std::string& root_name = ppapi::IsolatedFileSystemTypeToRootName(PP_ISOLATEDFILESYSTEMTYPE_PRIVATE_PLUGINPRIVATE); + const std::string& fsid = + storage::IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath( + storage::kFileSystemTypePluginPrivate, root_name, base::FilePath()); + + // Grant full access of isolated filesystem to renderer process. + content::ChildProcessSecurityPolicy* policy = content::ChildProcessSecurityPolicy::GetInstance(); + policy->GrantCreateReadWriteFileSystem(m_render_process_id, fsid); + + context->reply_msg = PpapiPluginMsg_IsolatedFileSystem_BrowserOpenReply(fsid); + return PP_OK; +} + +} // namespace chrome diff --git a/src/core/renderer/pepper/pepper_isolated_file_system_message_filter.h b/src/core/renderer/pepper/pepper_isolated_file_system_message_filter.h new file mode 100644 index 000000000..750f7cea0 --- /dev/null +++ b/src/core/renderer/pepper/pepper_isolated_file_system_message_filter.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PEPPER_ISOLATED_FILE_SYSTEM_MESSAGE_FILTER_H +#define PEPPER_ISOLATED_FILE_SYSTEM_MESSAGE_FILTER_H + +#include "base/macros.h" +#include "ppapi/c/pp_instance.h" +#include "ppapi/c/pp_resource.h" +#include "ppapi/c/private/ppb_isolated_file_system_private.h" +#include "ppapi/host/resource_host.h" +#include "ppapi/host/resource_message_filter.h" + +namespace content { +class BrowserPpapiHost; +} + +namespace ppapi { +namespace host { +struct HostMessageContext; +} // namespace host +} // namespace ppapi + +namespace QtWebEngineCore { + +class PepperIsolatedFileSystemMessageFilter : public ppapi::host::ResourceMessageFilter { +public: + static PepperIsolatedFileSystemMessageFilter *Create(PP_Instance instance, content::BrowserPpapiHost *host); + + // ppapi::host::ResourceMessageFilter implementation. + scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(const IPC::Message &msg) override; + int32_t OnResourceMessageReceived(const IPC::Message &msg, ppapi::host::HostMessageContext *context) override; + +private: + PepperIsolatedFileSystemMessageFilter(int render_process_id, ppapi::host::PpapiHost *ppapi_host); + + ~PepperIsolatedFileSystemMessageFilter() override; + + + int32_t OnOpenFileSystem(ppapi::host::HostMessageContext *context, PP_IsolatedFileSystemType_Private type); + int32_t OpenPluginPrivateFileSystem(ppapi::host::HostMessageContext *context); + + const int m_render_process_id; + + // Not owned by this object. + ppapi::host::PpapiHost* m_ppapi_host; + + DISALLOW_COPY_AND_ASSIGN(PepperIsolatedFileSystemMessageFilter); +}; + +} // namespace QtWebEngineCore + +#endif // PEPPER_ISOLATED_FILE_SYSTEM_MESSAGE_FILTER_H diff --git a/src/core/renderer/pepper/pepper_renderer_host_factory_qt.cpp b/src/core/renderer/pepper/pepper_renderer_host_factory_qt.cpp index 8d1689b0e..636ca12f1 100644 --- a/src/core/renderer/pepper/pepper_renderer_host_factory_qt.cpp +++ b/src/core/renderer/pepper/pepper_renderer_host_factory_qt.cpp @@ -37,6 +37,11 @@ ** ****************************************************************************/ +// This is based on chrome/renderer/pepper/chrome_renderer_pepper_host_factory.cc: +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + #include "pepper_renderer_host_factory_qt.h" #include "pepper_flash_renderer_host_qt.h" #include "content/public/renderer/renderer_ppapi_host.h" diff --git a/src/core/renderer/render_frame_observer_qt.cpp b/src/core/renderer/render_frame_observer_qt.cpp index 78ba0e9e6..f2285f298 100644 --- a/src/core/renderer/render_frame_observer_qt.cpp +++ b/src/core/renderer/render_frame_observer_qt.cpp @@ -37,6 +37,11 @@ ** ****************************************************************************/ +// This is based on chrome/renderer/pepper/pepper_helper.cc: +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + #include "render_frame_observer_qt.h" #include "content/public/renderer/renderer_ppapi_host.h" diff --git a/src/core/ssl_host_state_delegate_qt.cpp b/src/core/ssl_host_state_delegate_qt.cpp index cf17b944c..506172aaa 100644 --- a/src/core/ssl_host_state_delegate_qt.cpp +++ b/src/core/ssl_host_state_delegate_qt.cpp @@ -72,8 +72,7 @@ void CertPolicy::Allow(const net::X509Certificate& cert, net::CertStatus error) m_allowed[fingerprint] |= error; } -SSLHostStateDelegateQt::SSLHostStateDelegateQt(BrowserContextAdapter *contextAdapter) - : m_contextAdapter(contextAdapter) +SSLHostStateDelegateQt::SSLHostStateDelegateQt() { } diff --git a/src/core/ssl_host_state_delegate_qt.h b/src/core/ssl_host_state_delegate_qt.h index 7c91fcb2d..64a430094 100644 --- a/src/core/ssl_host_state_delegate_qt.h +++ b/src/core/ssl_host_state_delegate_qt.h @@ -57,7 +57,7 @@ private: class SSLHostStateDelegateQt : public content::SSLHostStateDelegate { public: - SSLHostStateDelegateQt(BrowserContextAdapter *); + SSLHostStateDelegateQt(); ~SSLHostStateDelegateQt(); // content::SSLHostStateDelegate implementation: @@ -71,7 +71,6 @@ public: virtual bool HasAllowException(const std::string &host) const override; private: - BrowserContextAdapter *m_contextAdapter; std::map<std::string, CertPolicy> m_certPolicyforHost; }; diff --git a/src/core/type_conversion.cpp b/src/core/type_conversion.cpp index ccfc2fdc6..ef220b86c 100644 --- a/src/core/type_conversion.cpp +++ b/src/core/type_conversion.cpp @@ -197,5 +197,4 @@ FaviconInfo toFaviconInfo(const content::FaviconURL &favicon_url) return info; } - } // namespace QtWebEngineCore diff --git a/src/core/type_conversion.h b/src/core/type_conversion.h index 84f91ec3e..e96a544e5 100644 --- a/src/core/type_conversion.h +++ b/src/core/type_conversion.h @@ -85,6 +85,11 @@ inline QString toQt(const std::string &string) return QString::fromStdString(string); } +inline QByteArray toQByteArray(const std::string &string) +{ + return QByteArray::fromStdString(string); +} + inline base::string16 toString16(const QString &qString) { #if defined(OS_WIN) diff --git a/src/core/url_request_context_getter_qt.cpp b/src/core/url_request_context_getter_qt.cpp index f80aa194b..afbb66b95 100644 --- a/src/core/url_request_context_getter_qt.cpp +++ b/src/core/url_request_context_getter_qt.cpp @@ -89,24 +89,28 @@ static const char kQrcSchemeQt[] = "qrc"; using content::BrowserThread; -URLRequestContextGetterQt::URLRequestContextGetterQt(BrowserContextAdapter *browserContext, content::ProtocolHandlerMap *protocolHandlers, content::URLRequestInterceptorScopedVector request_interceptors) +URLRequestContextGetterQt::URLRequestContextGetterQt(QSharedPointer<BrowserContextAdapter> browserContext, content::ProtocolHandlerMap *protocolHandlers, content::URLRequestInterceptorScopedVector request_interceptors) : m_ignoreCertificateErrors(false) , m_browserContext(browserContext) + , m_baseJobFactory(0) , m_cookieDelegate(new CookieMonsterDelegateQt()) , m_requestInterceptors(std::move(request_interceptors)) { std::swap(m_protocolHandlers, *protocolHandlers); + m_cookieDelegate->setClient(m_browserContext->cookieStore()); updateStorageSettings(); } URLRequestContextGetterQt::~URLRequestContextGetterQt() { + m_cookieDelegate->setCookieMonster(0); // this will let CookieMonsterDelegateQt be deleted delete m_proxyConfigService.fetchAndStoreAcquire(0); } net::URLRequestContext *URLRequestContextGetterQt::GetURLRequestContext() { + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); if (!m_urlRequestContext) { m_urlRequestContext.reset(new net::URLRequestContext()); @@ -123,14 +127,16 @@ net::URLRequestContext *URLRequestContextGetterQt::GetURLRequestContext() void URLRequestContextGetterQt::updateStorageSettings() { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + // m_proxyConfigService having a non-null value is used to indicate + // storage is already being updated. if (!m_proxyConfigService.loadAcquire()) { // We must create the proxy config service on the UI loop on Linux because it // must synchronously run on the glib message loop. This will be passed to // the URLRequestContextStorage on the IO thread in GetURLRequestContext(). - m_proxyConfigService = new ProxyConfigServiceQt(net::ProxyService::CreateSystemProxyConfigService( + m_proxyConfigService.storeRelease(new ProxyConfigServiceQt(net::ProxyService::CreateSystemProxyConfigService( content::BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), content::BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE) - )); + ))); if (m_storage) { content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestContextGetterQt::generateStorage, this)); } @@ -154,6 +160,7 @@ void URLRequestContextGetterQt::cancelAllUrlRequests() void URLRequestContextGetterQt::generateStorage() { + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); Q_ASSERT(m_urlRequestContext); // We must stop all requests before deleting their backends. @@ -206,14 +213,15 @@ void URLRequestContextGetterQt::generateStorage() void URLRequestContextGetterQt::updateCookieStore() { - if (m_urlRequestContext && !m_updateCookieStore && !m_proxyConfigService) { - m_updateCookieStore = 1; + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + // Do not trigger an update if another is already triggered, or we are not yet initialized. + if (m_urlRequestContext && !m_proxyConfigService && !m_updateCookieStore.fetchAndStoreRelaxed(1)) content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestContextGetterQt::generateCookieStore, this)); - } } void URLRequestContextGetterQt::generateCookieStore() { + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); Q_ASSERT(m_urlRequestContext); Q_ASSERT(m_storage); m_updateCookieStore = 0; @@ -221,7 +229,6 @@ void URLRequestContextGetterQt::generateCookieStore() // Unset it first to get a chance to destroy and flush the old cookie store before opening a new on possibly the same file. m_storage->set_cookie_store(0); m_cookieDelegate->setCookieMonster(0); - m_cookieDelegate->setClient(m_browserContext->cookieStore()); net::CookieStore* cookieStore = 0; switch (m_browserContext->persistentCookiesPolicy()) { @@ -262,51 +269,38 @@ void URLRequestContextGetterQt::generateCookieStore() void URLRequestContextGetterQt::updateUserAgent() { + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + // Do not trigger an update if all storage settings are already being updated if (m_urlRequestContext && !m_proxyConfigService) content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestContextGetterQt::generateUserAgent, this)); } -class HttpUserAgentSettingsQt : public net::HttpUserAgentSettings -{ - const BrowserContextAdapter *m_browserContext; -public: - HttpUserAgentSettingsQt(const BrowserContextAdapter *ctx) - : m_browserContext(ctx) - { - } - - std::string GetAcceptLanguage() const Q_DECL_OVERRIDE - { - return m_browserContext->httpAcceptLanguage().toStdString(); - } - - std::string GetUserAgent() const Q_DECL_OVERRIDE - { - return m_browserContext->httpUserAgent().toStdString(); - } -}; - void URLRequestContextGetterQt::generateUserAgent() { + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); Q_ASSERT(m_urlRequestContext); Q_ASSERT(m_storage); - m_storage->set_http_user_agent_settings(scoped_ptr<net::HttpUserAgentSettings>(new HttpUserAgentSettingsQt(m_browserContext.constData()))); + m_storage->set_http_user_agent_settings(scoped_ptr<net::HttpUserAgentSettings>( + new net::StaticHttpUserAgentSettings(m_browserContext->httpAcceptLanguage().toStdString(), m_browserContext->httpUserAgent().toStdString()))); } void URLRequestContextGetterQt::updateHttpCache() { - if (m_urlRequestContext && !m_updateHttpCache && !m_proxyConfigService) { - m_updateHttpCache = 1; + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + // Do not trigger a new update if another is already triggered + if (m_urlRequestContext && !m_proxyConfigService && !m_updateHttpCache.fetchAndStoreRelaxed(1)) content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestContextGetterQt::generateHttpCache, this)); - } } void URLRequestContextGetterQt::updateJobFactory() { - Q_ASSERT(m_jobFactory); + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestContextGetterQt::generateJobFactory, this)); + if (m_urlRequestContext && !m_updateJobFactory.fetchAndStoreRelaxed(1)) + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::Bind(&URLRequestContextGetterQt::regenerateJobFactory, + this, m_browserContext->customUrlSchemes())); } static bool doNetworkSessionParamsMatch(const net::HttpNetworkSession::Params &first, const net::HttpNetworkSession::Params &second) @@ -357,6 +351,7 @@ net::HttpNetworkSession::Params URLRequestContextGetterQt::generateNetworkSessio void URLRequestContextGetterQt::generateHttpCache() { + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); Q_ASSERT(m_urlRequestContext); Q_ASSERT(m_storage); @@ -420,9 +415,10 @@ void URLRequestContextGetterQt::clearCurrentCacheBackend() void URLRequestContextGetterQt::generateJobFactory() { + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); Q_ASSERT(m_urlRequestContext); + Q_ASSERT(!m_jobFactory); - m_jobFactory.reset(); scoped_ptr<net::URLRequestJobFactoryImpl> jobFactory(new net::URLRequestJobFactoryImpl()); { @@ -430,6 +426,7 @@ void URLRequestContextGetterQt::generateJobFactory() content::ProtocolHandlerMap::iterator it = m_protocolHandlers.find(url::kBlobScheme); Q_ASSERT(it != m_protocolHandlers.end()); jobFactory->SetProtocolHandler(it->first, scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(it->second.release())); + m_protocolHandlers.clear(); } jobFactory->SetProtocolHandler(url::kDataScheme, scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(new net::DataProtocolHandler())); @@ -440,10 +437,12 @@ void URLRequestContextGetterQt::generateJobFactory() jobFactory->SetProtocolHandler(url::kFtpScheme, scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(new net::FtpProtocolHandler(new net::FtpNetworkLayer(m_urlRequestContext->host_resolver())))); - QHash<QByteArray, QWebEngineUrlSchemeHandler*>::const_iterator it = m_browserContext->customUrlSchemeHandlers().constBegin(); - const QHash<QByteArray, QWebEngineUrlSchemeHandler*>::const_iterator end = m_browserContext->customUrlSchemeHandlers().constEnd(); - for (; it != end; ++it) - jobFactory->SetProtocolHandler(it.key().toStdString(), scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(new CustomProtocolHandler(it.value()))); + m_installedCustomSchemes = m_browserContext->customUrlSchemes(); + Q_FOREACH (const QByteArray &scheme, m_installedCustomSchemes) { + jobFactory->SetProtocolHandler(scheme.toStdString(), scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(new CustomProtocolHandler(m_browserContext))); + } + + m_baseJobFactory = jobFactory.get(); // Set up interceptors in the reverse order. scoped_ptr<net::URLRequestJobFactory> topJobFactory = std::move(jobFactory); @@ -458,6 +457,27 @@ void URLRequestContextGetterQt::generateJobFactory() m_urlRequestContext->set_job_factory(m_jobFactory.get()); } +void URLRequestContextGetterQt::regenerateJobFactory(const QList<QByteArray> customSchemes) +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + Q_ASSERT(m_urlRequestContext); + Q_ASSERT(m_jobFactory); + Q_ASSERT(m_baseJobFactory); + + m_updateJobFactory.storeRelease(0); + if (customSchemes == m_installedCustomSchemes) + return; + + Q_FOREACH (const QByteArray &scheme, m_installedCustomSchemes) { + m_baseJobFactory->SetProtocolHandler(scheme.toStdString(), nullptr); + } + + m_installedCustomSchemes = customSchemes; + Q_FOREACH (const QByteArray &scheme, m_installedCustomSchemes) { + m_baseJobFactory->SetProtocolHandler(scheme.toStdString(), scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(new CustomProtocolHandler(m_browserContext))); + } +} + scoped_refptr<base::SingleThreadTaskRunner> URLRequestContextGetterQt::GetNetworkTaskRunner() const { return content::BrowserThread::GetMessageLoopProxyForThread(content::BrowserThread::IO); diff --git a/src/core/url_request_context_getter_qt.h b/src/core/url_request_context_getter_qt.h index 13d6e2f72..7078c7a44 100644 --- a/src/core/url_request_context_getter_qt.h +++ b/src/core/url_request_context_getter_qt.h @@ -56,8 +56,9 @@ #include "cookie_monster_delegate_qt.h" #include "network_delegate_qt.h" -#include "qglobal.h" -#include <qatomic.h> +#include <QtCore/qglobal.h> +#include <QtCore/qatomic.h> +#include <QtCore/qsharedpointer.h> namespace net { class MappedHostResolver; @@ -70,7 +71,7 @@ class BrowserContextAdapter; class URLRequestContextGetterQt : public net::URLRequestContextGetter { public: - explicit URLRequestContextGetterQt(BrowserContextAdapter *browserContext, content::ProtocolHandlerMap *protocolHandlers, content::URLRequestInterceptorScopedVector request_interceptors); + URLRequestContextGetterQt(QSharedPointer<BrowserContextAdapter> browserContext, content::ProtocolHandlerMap *protocolHandlers, content::URLRequestInterceptorScopedVector request_interceptors); virtual net::URLRequestContext *GetURLRequestContext() Q_DECL_OVERRIDE; virtual scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() const Q_DECL_OVERRIDE; @@ -92,6 +93,7 @@ private: void generateHttpCache(); void generateUserAgent(); void generateJobFactory(); + void regenerateJobFactory(const QList<QByteArray> customSchemes); void clearCurrentCacheBackend(); void cancelAllUrlRequests(); net::HttpNetworkSession::Params generateNetworkSessionParams(); @@ -99,7 +101,8 @@ private: bool m_ignoreCertificateErrors; QAtomicInt m_updateCookieStore; QAtomicInt m_updateHttpCache; - QExplicitlySharedDataPointer<BrowserContextAdapter> m_browserContext; + QAtomicInt m_updateJobFactory; + QSharedPointer<BrowserContextAdapter> m_browserContext; content::ProtocolHandlerMap m_protocolHandlers; QAtomicPointer<net::ProxyConfigService> m_proxyConfigService; @@ -107,10 +110,12 @@ private: scoped_ptr<NetworkDelegateQt> m_networkDelegate; scoped_ptr<net::URLRequestContextStorage> m_storage; scoped_ptr<net::URLRequestJobFactory> m_jobFactory; + net::URLRequestJobFactoryImpl *m_baseJobFactory; scoped_ptr<net::DhcpProxyScriptFetcherFactory> m_dhcpProxyScriptFetcherFactory; scoped_refptr<CookieMonsterDelegateQt> m_cookieDelegate; content::URLRequestInterceptorScopedVector m_requestInterceptors; scoped_ptr<net::HttpNetworkSession> m_httpNetworkSession; + QList<QByteArray> m_installedCustomSchemes; friend class NetworkDelegateQt; }; diff --git a/src/core/url_request_custom_job.cpp b/src/core/url_request_custom_job.cpp index 79a54650c..921be0b41 100644 --- a/src/core/url_request_custom_job.cpp +++ b/src/core/url_request_custom_job.cpp @@ -42,6 +42,7 @@ #include "api/qwebengineurlrequestjob.h" #include "api/qwebengineurlschemehandler.h" +#include "browser_context_adapter.h" #include "type_conversion.h" #include "content/public/browser/browser_thread.h" @@ -57,9 +58,11 @@ using namespace net; namespace QtWebEngineCore { -URLRequestCustomJob::URLRequestCustomJob(URLRequest *request, NetworkDelegate *networkDelegate, QWebEngineUrlSchemeHandler *schemeHandler) +URLRequestCustomJob::URLRequestCustomJob(URLRequest *request, NetworkDelegate *networkDelegate, + const std::string &scheme, QWeakPointer<const BrowserContextAdapter> adapter) : URLRequestJob(request, networkDelegate) - , m_schemeHandler(schemeHandler) + , m_scheme(scheme) + , m_adapter(adapter) , m_shared(new URLRequestCustomJobShared(this)) { } @@ -328,11 +331,22 @@ void URLRequestCustomJobShared::startAsync() delete this; return; } - m_delegate = new URLRequestCustomJobDelegate(this); - m_asyncInitialized = true; - QWebEngineUrlRequestJob *requestJob = new QWebEngineUrlRequestJob(m_delegate); - if (m_job) - m_job->m_schemeHandler->requestStarted(requestJob); + + QWebEngineUrlSchemeHandler *schemeHandler = 0; + QSharedPointer<const BrowserContextAdapter> browserContext = m_job->m_adapter.toStrongRef(); + if (browserContext) + schemeHandler = browserContext->customUrlSchemeHandlers()[toQByteArray(m_job->m_scheme)]; + if (schemeHandler) { + m_delegate = new URLRequestCustomJobDelegate(this); + m_asyncInitialized = true; + QWebEngineUrlRequestJob *requestJob = new QWebEngineUrlRequestJob(m_delegate); + schemeHandler->requestStarted(requestJob); + } else { + lock.unlock(); + abort(); + delete this; + return; + } } } // namespace diff --git a/src/core/url_request_custom_job.h b/src/core/url_request_custom_job.h index e9f48216b..226c39e68 100644 --- a/src/core/url_request_custom_job.h +++ b/src/core/url_request_custom_job.h @@ -48,17 +48,17 @@ #include <QtCore/QPointer> QT_FORWARD_DECLARE_CLASS(QIODevice) -QT_FORWARD_DECLARE_CLASS(QWebEngineUrlSchemeHandler) namespace QtWebEngineCore { +class BrowserContextAdapter; class URLRequestCustomJobDelegate; class URLRequestCustomJobShared; // A request job that handles reading custom URL schemes class URLRequestCustomJob : public net::URLRequestJob { public: - URLRequestCustomJob(net::URLRequest *request, net::NetworkDelegate *networkDelegate, QWebEngineUrlSchemeHandler *schemeHandler); + URLRequestCustomJob(net::URLRequest *request, net::NetworkDelegate *networkDelegate, const std::string &scheme, QWeakPointer<const BrowserContextAdapter> adapter); virtual void Start() Q_DECL_OVERRIDE; virtual void Kill() Q_DECL_OVERRIDE; virtual int ReadRawData(net::IOBuffer* buf, int buf_size) Q_DECL_OVERRIDE;; @@ -70,7 +70,8 @@ protected: virtual ~URLRequestCustomJob(); private: - QWebEngineUrlSchemeHandler *m_schemeHandler; + std::string m_scheme; + QWeakPointer<const BrowserContextAdapter> m_adapter; URLRequestCustomJobShared *m_shared; friend class URLRequestCustomJobShared; diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index 1d937b62d..116cd704e 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -517,6 +517,7 @@ void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeT params.virtual_url_for_data_url = baseUrl.isEmpty() ? GURL(url::kAboutBlankURL) : toGurl(baseUrl); params.can_load_local_resources = true; params.transition_type = ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_API); + params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE; d->webContents->GetController().LoadURLWithParams(params); d->webContents->Focus(); } @@ -708,7 +709,15 @@ void WebContentsAdapter::setZoomFactor(qreal factor) Q_D(WebContentsAdapter); if (factor < content::kMinimumZoomFactor || factor > content::kMaximumZoomFactor) return; - content::HostZoomMap::SetZoomLevel(d->webContents.get(), content::ZoomFactorToZoomLevel(static_cast<double>(factor))); + + double zoomLevel = content::ZoomFactorToZoomLevel(static_cast<double>(factor)); + content::HostZoomMap *zoomMap = content::HostZoomMap::GetForWebContents(d->webContents.get()); + + if (zoomMap) { + int render_process_id = d->webContents->GetRenderProcessHost()->GetID(); + int render_view_id = d->webContents->GetRenderViewHost()->GetRoutingID(); + zoomMap->SetTemporaryZoomLevel(render_process_id, render_view_id, zoomLevel); + } } qreal WebContentsAdapter::currentZoomFactor() const diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h index f99cedcad..80aabaa4d 100644 --- a/src/core/web_contents_adapter_client.h +++ b/src/core/web_contents_adapter_client.h @@ -258,8 +258,9 @@ public: virtual void startDragging(const content::DropData &dropData, Qt::DropActions allowedActions, const QPixmap &pixmap, const QPoint &offset) = 0; - virtual BrowserContextAdapter* browserContextAdapter() = 0; + virtual QSharedPointer<BrowserContextAdapter> browserContextAdapter() = 0; virtual WebContentsAdapter* webContentsAdapter() = 0; + }; } // namespace QtWebEngineCore diff --git a/src/core/web_contents_adapter_p.h b/src/core/web_contents_adapter_p.h index 0507ebf4a..5c0e83298 100644 --- a/src/core/web_contents_adapter_p.h +++ b/src/core/web_contents_adapter_p.h @@ -57,8 +57,8 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" -#include <QExplicitlySharedDataPointer> #include <QScopedPointer> +#include <QSharedPointer> QT_FORWARD_DECLARE_CLASS(QTimer) QT_FORWARD_DECLARE_CLASS(QWebChannel) @@ -83,7 +83,7 @@ public: WebContentsAdapterPrivate(); ~WebContentsAdapterPrivate(); scoped_refptr<WebEngineContext> engineContext; - QExplicitlySharedDataPointer<BrowserContextAdapter> browserContextAdapter; + QSharedPointer<BrowserContextAdapter> browserContextAdapter; scoped_ptr<content::WebContents> webContents; scoped_ptr<WebContentsDelegateQt> webContentsDelegate; scoped_ptr<RenderViewObserverHostQt> renderViewObserverHost; diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index b3bfc432b..6da80e94d 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -164,7 +164,7 @@ namespace QtWebEngineCore { void WebEngineContext::destroyBrowserContext() { - m_defaultBrowserContext = 0; + m_defaultBrowserContext.reset(); } void WebEngineContext::destroy() @@ -198,11 +198,11 @@ scoped_refptr<WebEngineContext> WebEngineContext::current() return sContext; } -BrowserContextAdapter* WebEngineContext::defaultBrowserContext() +QSharedPointer<BrowserContextAdapter> WebEngineContext::defaultBrowserContext() { if (!m_defaultBrowserContext) - m_defaultBrowserContext = new BrowserContextAdapter(QStringLiteral("Default")); - return m_defaultBrowserContext.data(); + m_defaultBrowserContext = QSharedPointer<BrowserContextAdapter>::create(QStringLiteral("Default")); + return m_defaultBrowserContext; } QObject *WebEngineContext::globalQObject() diff --git a/src/core/web_engine_context.h b/src/core/web_engine_context.h index 3c69d87ca..960f8ed47 100644 --- a/src/core/web_engine_context.h +++ b/src/core/web_engine_context.h @@ -47,7 +47,7 @@ #include "base/values.h" #include "components/devtools_http_handler/devtools_http_handler.h" -#include <QExplicitlySharedDataPointer> +#include <QSharedPointer> namespace base { class RunLoop; @@ -76,7 +76,7 @@ class WebEngineContext : public base::RefCounted<WebEngineContext> { public: static scoped_refptr<WebEngineContext> current(); - QtWebEngineCore::BrowserContextAdapter *defaultBrowserContext(); + QSharedPointer<QtWebEngineCore::BrowserContextAdapter> defaultBrowserContext(); QObject *globalQObject(); #if defined(ENABLE_BASIC_PRINTING) printing::PrintJobManager* getPrintJobManager(); @@ -94,7 +94,7 @@ private: scoped_ptr<content::ContentMainRunner> m_contentRunner; scoped_ptr<content::BrowserMainRunner> m_browserRunner; QObject* m_globalQObject; - QExplicitlySharedDataPointer<BrowserContextAdapter> m_defaultBrowserContext; + QSharedPointer<QtWebEngineCore::BrowserContextAdapter> m_defaultBrowserContext; scoped_ptr<devtools_http_handler::DevToolsHttpHandler> m_devtools; #if defined(ENABLE_BASIC_PRINTING) scoped_ptr<printing::PrintJobManager> m_printJobManager; diff --git a/src/core/web_engine_settings.cpp b/src/core/web_engine_settings.cpp index 54c7f7c4f..6c17c3ce9 100644 --- a/src/core/web_engine_settings.cpp +++ b/src/core/web_engine_settings.cpp @@ -222,7 +222,6 @@ void WebEngineSettings::initDefaults(bool offTheRecord) s_defaultAttributes.insert(PluginsEnabled, false); s_defaultAttributes.insert(FullScreenSupportEnabled, false); s_defaultAttributes.insert(ScreenCaptureEnabled, false); - s_defaultAttributes.insert(WebAudioEnabled, false); // The following defaults matches logic in render_view_host_impl.cc // But first we must ensure the WebContext has been initialized QtWebEngineCore::WebEngineContext::current(); @@ -312,7 +311,6 @@ void WebEngineSettings::applySettingsToWebPreferences(content::WebPreferences *p prefs->plugins_enabled = testAttribute(PluginsEnabled); prefs->fullscreen_supported = testAttribute(FullScreenSupportEnabled); prefs->accelerated_2d_canvas_enabled = testAttribute(Accelerated2dCanvasEnabled); - prefs->webaudio_enabled = testAttribute(WebAudioEnabled); prefs->experimental_webgl_enabled = testAttribute(WebGLEnabled); // Fonts settings. diff --git a/src/core/web_engine_settings.h b/src/core/web_engine_settings.h index 3bc108115..b623f1ec2 100644 --- a/src/core/web_engine_settings.h +++ b/src/core/web_engine_settings.h @@ -78,7 +78,6 @@ public: FullScreenSupportEnabled, ScreenCaptureEnabled, WebGLEnabled, - WebAudioEnabled, Accelerated2dCanvasEnabled, AutoLoadIconsForPage, TouchIconsEnabled diff --git a/src/core/yuv_video_node.cpp b/src/core/yuv_video_node.cpp index d5eee474f..f8290878b 100644 --- a/src/core/yuv_video_node.cpp +++ b/src/core/yuv_video_node.cpp @@ -37,6 +37,11 @@ ** ****************************************************************************/ +// Based on cc/output/gl_renderer.cc and cc/output/shader.cc: +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + #include "yuv_video_node.h" #include <QtGui/qopenglcontext.h> diff --git a/src/webengine/api/qquickwebenginefaviconprovider.cpp b/src/webengine/api/qquickwebenginefaviconprovider.cpp new file mode 100644 index 000000000..c41ec5a07 --- /dev/null +++ b/src/webengine/api/qquickwebenginefaviconprovider.cpp @@ -0,0 +1,186 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickwebenginefaviconprovider_p_p.h" + +#include "favicon_manager.h" +#include "qquickwebengineview_p.h" +#include "qquickwebengineview_p_p.h" +#include "web_contents_adapter.h" + +#include <QtGui/QIcon> +#include <QtGui/QPixmap> + +QT_BEGIN_NAMESPACE + +using QtWebEngineCore::FaviconInfo; +using QtWebEngineCore::FaviconManager; + +static inline unsigned area(const QSize &size) +{ + return size.width() * size.height(); +} + +QString QQuickWebEngineFaviconProvider::identifier() +{ + return QStringLiteral("favicon"); +} + +QUrl QQuickWebEngineFaviconProvider::faviconProviderUrl(const QUrl &url) +{ + if (url.isEmpty()) + return url; + + QUrl providerUrl; + providerUrl.setScheme(QStringLiteral("image")); + providerUrl.setHost(identifier()); + providerUrl.setPath(QStringLiteral("/%1").arg(url.toString())); + + return providerUrl; +} + +QQuickWebEngineFaviconProvider::QQuickWebEngineFaviconProvider() + : QQuickImageProvider(QQuickImageProvider::Pixmap) + , m_latestView(0) +{ +} + +QQuickWebEngineFaviconProvider::~QQuickWebEngineFaviconProvider() +{ + qDeleteAll(m_iconUrlMap); +} + +QUrl QQuickWebEngineFaviconProvider::attach(QQuickWebEngineView *view, const QUrl &iconUrl) +{ + if (iconUrl.isEmpty()) + return QUrl(); + + m_latestView = view; + + if (!m_iconUrlMap.contains(view)) + m_iconUrlMap.insert(view, new QList<QUrl>()); + + QList<QUrl> *iconUrls = m_iconUrlMap[view]; + if (!iconUrls->contains(iconUrl)) + iconUrls->append(iconUrl); + + return faviconProviderUrl(iconUrl); +} + +void QQuickWebEngineFaviconProvider::detach(QQuickWebEngineView *view) +{ + QList<QUrl> *iconUrls = m_iconUrlMap.take(view); + delete iconUrls; +} + +QPixmap QQuickWebEngineFaviconProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) +{ + Q_UNUSED(size); + Q_UNUSED(requestedSize); + + QUrl iconUrl(id); + QQuickWebEngineView *view = viewForIconUrl(iconUrl); + + if (!view || iconUrl.isEmpty()) + return QPixmap(); + + FaviconManager *faviconManager = view->d_ptr->adapter->faviconManager(); + Q_ASSERT(faviconManager); + + const QIcon &icon = faviconManager->getIcon(iconUrl); + + Q_ASSERT(!icon.isNull()); + const QSize &bestSize = faviconManager->getFaviconInfo(iconUrl).size; + + // If source size is not specified, use the best quality + if (!requestedSize.isValid()) { + if (size) + *size = bestSize; + + return icon.pixmap(bestSize).copy(); + } + + const QSize &fitSize = findFitSize(icon.availableSizes(), requestedSize, bestSize); + const QPixmap &iconPixmap = icon.pixmap(fitSize); + + if (size) + *size = iconPixmap.size(); + + return iconPixmap.scaled(requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation).copy(); +} + +QQuickWebEngineView *QQuickWebEngineFaviconProvider::viewForIconUrl(const QUrl &iconUrl) const +{ + // The most common use case is that the requested iconUrl belongs to the + // latest WebEngineView which was raised an iconChanged signal. + if (m_latestView) { + QList<QUrl> *iconUrls = m_iconUrlMap[m_latestView]; + if (iconUrls->contains(iconUrl)) + return m_latestView; + } + + for (auto it = m_iconUrlMap.cbegin(), end = m_iconUrlMap.cend(); it != end; ++it) { + if (it.value()->contains(iconUrl)) + return it.key(); + } + + return 0; +} + +QSize QQuickWebEngineFaviconProvider::findFitSize(const QList<QSize> &availableSizes, + const QSize &requestedSize, + const QSize &bestSize) const +{ + Q_ASSERT(availableSizes.count()); + if (availableSizes.count() == 1 || area(requestedSize) >= area(bestSize)) + return bestSize; + + QSize fitSize = bestSize; + for (const QSize &size : availableSizes) { + if (area(size) == area(requestedSize)) + return size; + + if (area(requestedSize) < area(size) && area(size) < area(fitSize)) + fitSize = size; + } + + return fitSize; +} + +QT_END_NAMESPACE diff --git a/src/webengine/api/qquickwebenginefaviconprovider_p_p.h b/src/webengine/api/qquickwebenginefaviconprovider_p_p.h new file mode 100644 index 000000000..52f3fb7a9 --- /dev/null +++ b/src/webengine/api/qquickwebenginefaviconprovider_p_p.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKWEBENGINEFAVICONPROVIDER_P_P_H +#define QQUICKWEBENGINEFAVICONPROVIDER_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <private/qtwebengineglobal_p.h> +#include <QtQuick/QQuickImageProvider> + +#include <QtCore/QMap> + +QT_BEGIN_NAMESPACE + +class QQuickWebEngineView; + +class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineFaviconProvider : public QQuickImageProvider { +public: + static QString identifier(); + static QUrl faviconProviderUrl(const QUrl &); + + QQuickWebEngineFaviconProvider(); + ~QQuickWebEngineFaviconProvider(); + + QUrl attach(QQuickWebEngineView *, const QUrl &); + void detach(QQuickWebEngineView *); + + + virtual QPixmap requestPixmap(const QString &, QSize *, const QSize &); + +private: + QQuickWebEngineView *viewForIconUrl(const QUrl &) const; + QSize findFitSize(const QList<QSize> &, const QSize &, const QSize &) const; + + QMap<QQuickWebEngineView *, QList<QUrl> *> m_iconUrlMap; + QQuickWebEngineView *m_latestView; +}; + +QT_END_NAMESPACE + +#endif // QQUICKWEBENGINEFAVICONPROVIDER_P_P_H diff --git a/src/webengine/api/qquickwebenginehistory.cpp b/src/webengine/api/qquickwebenginehistory.cpp index 96a4415e0..970bfb22d 100644 --- a/src/webengine/api/qquickwebenginehistory.cpp +++ b/src/webengine/api/qquickwebenginehistory.cpp @@ -39,6 +39,8 @@ #include "qquickwebenginehistory_p.h" #include "qquickwebenginehistory_p_p.h" + +#include "qquickwebenginefaviconprovider_p_p.h" #include "qquickwebengineloadrequest_p.h" #include "qquickwebengineview_p_p.h" #include "web_contents_adapter.h" @@ -133,8 +135,9 @@ int QQuickWebEngineForwardHistoryListModelPrivate::offsetForIndex(int index) con \brief A data model that represents the history of a web engine page. - The WebEngineHistoryListModel type exposes the \e title, \e url, and \e offset roles. The - \e title and \e url specify the title and URL of the visited page. The \e offset specifies + The WebEngineHistoryListModel type exposes the \e title, \e url, \e icon, and \e offset roles. + The \e title, \e url and \e icon specify the title, URL, and favicon of the visited page. + The \e offset specifies the position of the page in respect to the current page (0). A positive number indicates that the page was visited after the current page, whereas a negative number indicates that the page was visited before the current page. @@ -166,6 +169,7 @@ QHash<int, QByteArray> QQuickWebEngineHistoryListModel::roleNames() const roles[QQuickWebEngineHistory::UrlRole] = "url"; roles[QQuickWebEngineHistory::TitleRole] = "title"; roles[QQuickWebEngineHistory::OffsetRole] = "offset"; + roles[QQuickWebEngineHistory::IconUrlRole] = "icon"; return roles; } @@ -183,7 +187,7 @@ QVariant QQuickWebEngineHistoryListModel::data(const QModelIndex &index, int rol if (!index.isValid()) return QVariant(); - if (role < QQuickWebEngineHistory::UrlRole || role > QQuickWebEngineHistory::OffsetRole) + if (role < QQuickWebEngineHistory::UrlRole || role > QQuickWebEngineHistory::IconUrlRole) return QVariant(); if (role == QQuickWebEngineHistory::UrlRole) @@ -194,6 +198,12 @@ QVariant QQuickWebEngineHistoryListModel::data(const QModelIndex &index, int rol if (role == QQuickWebEngineHistory::OffsetRole) return d->offsetForIndex(index.row()); + + if (role == QQuickWebEngineHistory::IconUrlRole) { + QUrl iconUrl = QUrl(d->adapter()->getNavigationEntryIconUrl(d->index(index.row()))); + return QQuickWebEngineFaviconProvider::faviconProviderUrl(iconUrl); + } + return QVariant(); } @@ -223,7 +233,7 @@ QQuickWebEngineHistoryPrivate::~QQuickWebEngineHistoryPrivate() The WebEngineHistory type can be accessed by using the \l{WebEngineView::navigationHistory}{WebEngineView.navigationHistory} property. - The WebEngineHistory type providess the following WebEngineHistoryListModel data model objects: + The WebEngineHistory type provides the following WebEngineHistoryListModel data model objects: \list \li \c backItems, which contains the URLs of visited pages. @@ -253,7 +263,8 @@ QQuickWebEngineHistoryPrivate::~QQuickWebEngineHistoryPrivate() format of the list items. The appearance of each item of the list in the delegate can be defined separately (it is not web engine specific). - The model roles \e title and \e url specify the title and URL of the visited page. The \e offset + The model roles \e title, \e url, and \e icon specify the title, URL, and favicon of the + visited page. The \e offset role specifies the position of the page in respect to the current page (0). A positive number indicates that the page was visited after the current page, whereas a negative number indicates that the page was visited before the current page. @@ -283,9 +294,8 @@ QQuickWebEngineHistory::~QQuickWebEngineHistory() } /*! - \qmlproperty QQuickWebEngineHistoryListModel WebEngineHistory::items + \qmlproperty WebEngineHistoryListModel WebEngineHistory::items \readonly - \since QtWebEngine 1.1 URLs of back items, forward items, and the current item in the history. */ @@ -298,9 +308,8 @@ QQuickWebEngineHistoryListModel *QQuickWebEngineHistory::items() const } /*! - \qmlproperty QQuickWebEngineHistoryListModel WebEngineHistory::backItems + \qmlproperty WebEngineHistoryListModel WebEngineHistory::backItems \readonly - \since QtWebEngine 1.1 URLs of visited pages. */ @@ -313,9 +322,8 @@ QQuickWebEngineHistoryListModel *QQuickWebEngineHistory::backItems() const } /*! - \qmlproperty QQuickWebEngineHistoryListModel WebEngineHistory::forwardItems + \qmlproperty WebEngineHistoryListModel WebEngineHistory::forwardItems \readonly - \since QtWebEngine 1.1 URLs of the pages that were visited after visiting the current page. */ diff --git a/src/webengine/api/qquickwebenginehistory_p.h b/src/webengine/api/qquickwebenginehistory_p.h index 4dedf17da..22340e483 100644 --- a/src/webengine/api/qquickwebenginehistory_p.h +++ b/src/webengine/api/qquickwebenginehistory_p.h @@ -101,6 +101,7 @@ public: UrlRole = Qt::UserRole + 1, TitleRole = Qt::UserRole + 2, OffsetRole = Qt::UserRole + 3, + IconUrlRole = Qt::UserRole + 4, }; QQuickWebEngineHistoryListModel *items() const; diff --git a/src/webengine/api/qquickwebengineprofile.cpp b/src/webengine/api/qquickwebengineprofile.cpp index f38422966..d7a84c106 100644 --- a/src/webengine/api/qquickwebengineprofile.cpp +++ b/src/webengine/api/qquickwebengineprofile.cpp @@ -134,7 +134,7 @@ ASSERT_ENUMS_MATCH(QQuickWebEngineDownloadItem::MimeHtmlSaveFormat, QtWebEngineC The \a download argument holds the state of the finished download instance. */ -QQuickWebEngineProfilePrivate::QQuickWebEngineProfilePrivate(BrowserContextAdapter* browserContext) +QQuickWebEngineProfilePrivate::QQuickWebEngineProfilePrivate(QSharedPointer<BrowserContextAdapter> browserContext) : m_settings(new QQuickWebEngineSettings()) , m_browserContextRef(browserContext) { @@ -261,7 +261,7 @@ void QQuickWebEngineProfilePrivate::downloadUpdated(const DownloadItemInfo &info */ QQuickWebEngineProfile::QQuickWebEngineProfile(QObject *parent) : QObject(parent), - d_ptr(new QQuickWebEngineProfilePrivate(new BrowserContextAdapter(false))) + d_ptr(new QQuickWebEngineProfilePrivate(QSharedPointer<BrowserContextAdapter>::create(false))) { // Sets up the global WebEngineContext QQuickWebEngineProfile::defaultProfile(); @@ -822,8 +822,7 @@ void QQuickWebEngineProfile::removeUrlScheme(const QByteArray &scheme) void QQuickWebEngineProfile::removeAllUrlSchemeHandlers() { Q_D(QQuickWebEngineProfile); - d->browserContext()->customUrlSchemeHandlers().clear(); - d->browserContext()->updateCustomUrlSchemeHandlers(); + d->browserContext()->clearCustomUrlSchemeHandlers(); } void QQuickWebEngineProfile::destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler *obj) diff --git a/src/webengine/api/qquickwebengineprofile_p.h b/src/webengine/api/qquickwebengineprofile_p.h index f9bb08500..1ba1eb53f 100644 --- a/src/webengine/api/qquickwebengineprofile_p.h +++ b/src/webengine/api/qquickwebengineprofile_p.h @@ -58,6 +58,7 @@ #include <QExplicitlySharedDataPointer> #include <QMap> #include <QPointer> +#include <QSharedPointer> QT_BEGIN_NAMESPACE @@ -67,10 +68,10 @@ class QQuickWebEngineSettings; class QQuickWebEngineProfilePrivate : public QtWebEngineCore::BrowserContextAdapterClient { public: Q_DECLARE_PUBLIC(QQuickWebEngineProfile) - QQuickWebEngineProfilePrivate(QtWebEngineCore::BrowserContextAdapter* browserContext); + QQuickWebEngineProfilePrivate(QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext); ~QQuickWebEngineProfilePrivate(); - QtWebEngineCore::BrowserContextAdapter *browserContext() const { return m_browserContextRef.data(); } + QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext() const { return m_browserContextRef; } QQuickWebEngineSettings *settings() const { return m_settings.data(); } void cancelDownload(quint32 downloadId); @@ -83,7 +84,7 @@ private: friend class QQuickWebEngineViewPrivate; QQuickWebEngineProfile *q_ptr; QScopedPointer<QQuickWebEngineSettings> m_settings; - QExplicitlySharedDataPointer<QtWebEngineCore::BrowserContextAdapter> m_browserContextRef; + QSharedPointer<QtWebEngineCore::BrowserContextAdapter> m_browserContextRef; QMap<quint32, QPointer<QQuickWebEngineDownloadItem> > m_ongoingDownloads; }; diff --git a/src/webengine/api/qquickwebenginesettings.cpp b/src/webengine/api/qquickwebenginesettings.cpp index 73d3e34b9..9096dd604 100644 --- a/src/webengine/api/qquickwebenginesettings.cpp +++ b/src/webengine/api/qquickwebenginesettings.cpp @@ -264,19 +264,6 @@ bool QQuickWebEngineSettings::webGLEnabled() const } /*! - \qmlproperty bool WebEngineSettings::webAudioEnabled - \since QtWebEngine 1.3 - - Enables support for HTML 5 WebAudio. - - Disabled by default. -*/ -bool QQuickWebEngineSettings::webAudioEnabled() const -{ - return d_ptr->testAttribute(WebEngineSettings::WebAudioEnabled); -} - -/*! \qmlproperty bool WebEngineSettings::accelerated2dCanvasEnabled \since QtWebEngine 1.3 @@ -453,14 +440,6 @@ void QQuickWebEngineSettings::setWebGLEnabled(bool on) Q_EMIT webGLEnabledChanged(); } -void QQuickWebEngineSettings::setWebAudioEnabled(bool on) -{ - bool wasOn = d_ptr->testAttribute(WebEngineSettings::WebAudioEnabled); - d_ptr->setAttribute(WebEngineSettings::WebAudioEnabled, on); - if (wasOn != on) - Q_EMIT webAudioEnabledChanged(); -} - void QQuickWebEngineSettings::setAccelerated2dCanvasEnabled(bool on) { bool wasOn = d_ptr->testAttribute(WebEngineSettings::Accelerated2dCanvasEnabled); diff --git a/src/webengine/api/qquickwebenginesettings_p.h b/src/webengine/api/qquickwebenginesettings_p.h index 6a5fd290e..d380ee3d9 100644 --- a/src/webengine/api/qquickwebenginesettings_p.h +++ b/src/webengine/api/qquickwebenginesettings_p.h @@ -79,7 +79,6 @@ class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineSettings : public QObject { Q_PROPERTY(QString defaultTextEncoding READ defaultTextEncoding WRITE setDefaultTextEncoding NOTIFY defaultTextEncodingChanged REVISION 1) Q_PROPERTY(bool screenCaptureEnabled READ screenCaptureEnabled WRITE setScreenCaptureEnabled NOTIFY screenCaptureEnabledChanged REVISION 2) Q_PROPERTY(bool webGLEnabled READ webGLEnabled WRITE setWebGLEnabled NOTIFY webGLEnabledChanged REVISION 2) - Q_PROPERTY(bool webAudioEnabled READ webAudioEnabled WRITE setWebAudioEnabled NOTIFY webAudioEnabledChanged REVISION 2) Q_PROPERTY(bool accelerated2dCanvasEnabled READ accelerated2dCanvasEnabled WRITE setAccelerated2dCanvasEnabled NOTIFY accelerated2dCanvasEnabledChanged REVISION 2) Q_PROPERTY(bool autoLoadIconsForPage READ autoLoadIconsForPage WRITE setAutoLoadIconsForPage NOTIFY autoLoadIconsForPageChanged REVISION 2) Q_PROPERTY(bool touchIconsEnabled READ touchIconsEnabled WRITE setTouchIconsEnabled NOTIFY touchIconsEnabledChanged REVISION 2) @@ -103,7 +102,6 @@ public: QString defaultTextEncoding() const; bool screenCaptureEnabled() const; bool webGLEnabled() const; - bool webAudioEnabled() const; bool accelerated2dCanvasEnabled() const; bool autoLoadIconsForPage() const; bool touchIconsEnabled() const; @@ -124,7 +122,6 @@ public: void setDefaultTextEncoding(QString encoding); void setScreenCaptureEnabled(bool on); void setWebGLEnabled(bool on); - void setWebAudioEnabled(bool on); void setAccelerated2dCanvasEnabled(bool on); void setAutoLoadIconsForPage(bool on); void setTouchIconsEnabled(bool on); @@ -146,7 +143,6 @@ signals: Q_REVISION(1) void defaultTextEncodingChanged(); Q_REVISION(2) void screenCaptureEnabledChanged(); Q_REVISION(2) void webGLEnabledChanged(); - Q_REVISION(2) void webAudioEnabledChanged(); Q_REVISION(2) void accelerated2dCanvasEnabledChanged(); Q_REVISION(2) void autoLoadIconsForPageChanged(); Q_REVISION(2) void touchIconsEnabledChanged(); diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index 9296cc4dd..f265ccfb6 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -47,6 +47,7 @@ #include "javascript_dialog_controller.h" #include "qquickwebenginehistory_p.h" #include "qquickwebenginecertificateerror_p.h" +#include "qquickwebenginefaviconprovider_p_p.h" #include "qquickwebengineloadrequest_p.h" #include "qquickwebenginenavigationrequest_p.h" #include "qquickwebenginenewviewrequest_p.h" @@ -112,6 +113,7 @@ QQuickWebEngineViewPrivate::QQuickWebEngineViewPrivate() , m_testSupport(0) #endif , contextMenuExtraItems(0) + , faviconProvider(0) , loadProgress(0) , m_fullscreenMode(false) , isLoading(false) @@ -121,6 +123,7 @@ QQuickWebEngineViewPrivate::QQuickWebEngineViewPrivate() , m_webChannelWorld(0) , m_dpiScale(1.0) , m_backgroundColor(Qt::white) + , m_defaultZoomFactor(1.0) { // The gold standard for mobile web content is 160 dpi, and the devicePixelRatio expected // is the (possibly quantized) ratio of device dpi to 160 dpi. @@ -389,9 +392,20 @@ void QQuickWebEngineViewPrivate::urlChanged(const QUrl &url) void QQuickWebEngineViewPrivate::iconChanged(const QUrl &url) { Q_Q(QQuickWebEngineView); - if (iconUrl == url) + + if (iconUrl == QQuickWebEngineFaviconProvider::faviconProviderUrl(url)) return; - iconUrl = url; + + if (!faviconProvider) { + QQmlEngine *engine = qmlEngine(q); + Q_ASSERT(engine); + faviconProvider = static_cast<QQuickWebEngineFaviconProvider *>( + engine->imageProvider(QQuickWebEngineFaviconProvider::identifier())); + Q_ASSERT(faviconProvider); + } + + iconUrl = faviconProvider->attach(q, url); + m_history->reset(); Q_EMIT q->iconChanged(); } @@ -640,7 +654,7 @@ QObject *QQuickWebEngineViewPrivate::accessibilityParentObject() } #endif // QT_NO_ACCESSIBILITY -BrowserContextAdapter *QQuickWebEngineViewPrivate::browserContextAdapter() +QSharedPointer<BrowserContextAdapter> QQuickWebEngineViewPrivate::browserContextAdapter() { return m_profile->d_ptr->browserContext(); } @@ -759,6 +773,10 @@ void QQuickWebEngineViewPrivate::adoptWebContents(WebContentsAdapter *webContent Q_FOREACH (QQuickWebEngineScript *script, m_userScripts) script->d_func()->bind(browserContextAdapter()->userResourceController(), adapter.data()); + // set the zoomFactor if it had been changed on the old adapter. + if (!qFuzzyCompare(adapter->currentZoomFactor(), m_defaultZoomFactor)) + q->setZoomFactor(m_defaultZoomFactor); + // Emit signals for values that might be different from the previous WebContentsAdapter. emit q->titleChanged(); emit q->urlChanged(); @@ -788,10 +806,14 @@ QQuickWebEngineView::QQuickWebEngineView(QQuickItem *parent) QQuickWebEngineView::~QQuickWebEngineView() { + Q_D(QQuickWebEngineView); + if (d->faviconProvider) + d->faviconProvider->detach(this); } void QQuickWebEngineViewPrivate::ensureContentsAdapter() { + Q_Q(QQuickWebEngineView); if (!adapter) { adapter = new WebContentsAdapter(); adapter->initialize(this); @@ -804,6 +826,10 @@ void QQuickWebEngineViewPrivate::ensureContentsAdapter() // push down the page's user scripts Q_FOREACH (QQuickWebEngineScript *script, m_userScripts) script->d_func()->bind(browserContextAdapter()->userResourceController(), adapter.data()); + // set the zoomFactor if it had been changed on the old adapter. + if (!qFuzzyCompare(adapter->currentZoomFactor(), m_defaultZoomFactor)) + q->setZoomFactor(m_defaultZoomFactor); + } } @@ -895,8 +921,11 @@ void QQuickWebEngineView::stop() void QQuickWebEngineView::setZoomFactor(qreal arg) { Q_D(QQuickWebEngineView); + d->m_defaultZoomFactor = arg; + if (!d->adapter) return; + qreal oldFactor = d->adapter->currentZoomFactor(); d->adapter->setZoomFactor(arg); if (qFuzzyCompare(oldFactor, d->adapter->currentZoomFactor())) @@ -1124,7 +1153,7 @@ qreal QQuickWebEngineView::zoomFactor() const { Q_D(const QQuickWebEngineView); if (!d->adapter) - return 1.0; + return d->m_defaultZoomFactor; return d->adapter->currentZoomFactor(); } diff --git a/src/webengine/api/qquickwebengineview_p.h b/src/webengine/api/qquickwebengineview_p.h index 8015820b7..843e34f42 100644 --- a/src/webengine/api/qquickwebengineview_p.h +++ b/src/webengine/api/qquickwebengineview_p.h @@ -60,6 +60,7 @@ QT_BEGIN_NAMESPACE class QQmlWebChannel; class QQuickWebEngineCertificateError; class QQuickWebEngineContextMenuData; +class QQuickWebEngineFaviconProvider; class QQuickWebEngineHistory; class QQuickWebEngineLoadRequest; class QQuickWebEngineNavigationRequest; @@ -517,6 +518,7 @@ private: friend class QQuickWebEngineViewExperimental; friend class QQuickWebEngineViewExperimentalExtension; friend class QQuickWebEngineNewViewRequest; + friend class QQuickWebEngineFaviconProvider; #ifndef QT_NO_ACCESSIBILITY friend class QQuickWebEngineViewAccessible; #endif // QT_NO_ACCESSIBILITY diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h index d240e3e50..82a9e9612 100644 --- a/src/webengine/api/qquickwebengineview_p_p.h +++ b/src/webengine/api/qquickwebengineview_p_p.h @@ -71,6 +71,7 @@ class QQuickWebEngineView; class QQmlComponent; class QQmlContext; class QQuickWebEngineSettings; +class QQuickWebEngineFaviconProvider; #ifdef ENABLE_QML_TESTSUPPORT_API class QQuickWebEngineTestSupport; @@ -187,7 +188,7 @@ public: void startDragging(const content::DropData &dropData, Qt::DropActions allowedActions, const QPixmap &pixmap, const QPoint &offset) Q_DECL_OVERRIDE; - virtual QtWebEngineCore::BrowserContextAdapter *browserContextAdapter() Q_DECL_OVERRIDE; + virtual QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContextAdapter() Q_DECL_OVERRIDE; QtWebEngineCore::WebContentsAdapter *webContentsAdapter() Q_DECL_OVERRIDE; void setDevicePixelRatio(qreal); @@ -215,6 +216,7 @@ public: QQuickWebEngineContextMenuData contextMenuData; QUrl explicitUrl; QUrl iconUrl; + QQuickWebEngineFaviconProvider *faviconProvider; int loadProgress; bool m_fullscreenMode; bool isLoading; @@ -230,6 +232,7 @@ private: QList<QQuickWebEngineScript *> m_userScripts; qreal m_dpiScale; QColor m_backgroundColor; + qreal m_defaultZoomFactor; }; #ifndef QT_NO_ACCESSIBILITY diff --git a/src/webengine/doc/src/qtwebengine-platform-notes.qdoc b/src/webengine/doc/src/qtwebengine-platform-notes.qdoc index c5f373029..dec9d0407 100644 --- a/src/webengine/doc/src/qtwebengine-platform-notes.qdoc +++ b/src/webengine/doc/src/qtwebengine-platform-notes.qdoc @@ -134,7 +134,7 @@ codecs can be enabled by passing the following option to qmake: \code - qmake WEBENGINE_CONFIG += use_proprietary_codecs + qmake WEBENGINE_CONFIG+=use_proprietary_codecs \endcode \warning When distributing proprietary codec libraries, you must acquire licenses for them. diff --git a/src/webengine/doc/src/webengineview.qdoc b/src/webengine/doc/src/webengineview.qdoc index 3bebb8cea..a070140c7 100644 --- a/src/webengine/doc/src/webengineview.qdoc +++ b/src/webengine/doc/src/webengineview.qdoc @@ -203,10 +203,11 @@ \qmlproperty url WebEngineView::icon \readonly - The location of the currently displayed web site icon, - also known as favicon or shortcut icon. This read-only URL corresponds to - the image used within a mobile browser application to represent a - bookmarked page on the device's home screen. + An internal URL for accessing the currently displayed web site icon, + also known as favicon or shortcut icon. The icon is already downloaded + and stored by the Qt WebEngine's favicon manager. + This read-only URL corresponds to the image used within a mobile browser + application to represent a bookmarked page on the device's home screen. The following snippet uses the \c{icon} property to build an \c{Image} component: @@ -214,7 +215,7 @@ \qml Image { id: appIcon - source: webView.icon != "" ? webView.icon : "fallbackFavIcon.png"; + source: webView.icon != "" ? webView.icon : "fallbackFavicon.png"; // ... } \endqml diff --git a/src/webengine/plugin/plugin.cpp b/src/webengine/plugin/plugin.cpp index fc8e40bd0..b71689a34 100644 --- a/src/webengine/plugin/plugin.cpp +++ b/src/webengine/plugin/plugin.cpp @@ -43,6 +43,7 @@ #include "qquickwebenginecertificateerror_p.h" #include "qquickwebenginedownloaditem_p.h" #include "qquickwebenginehistory_p.h" +#include "qquickwebenginefaviconprovider_p_p.h" #include "qquickwebengineloadrequest_p.h" #include "qquickwebenginenavigationrequest_p.h" #include "qquickwebenginenewviewrequest_p.h" @@ -63,6 +64,12 @@ class QtWebEnginePlugin : public QQmlExtensionPlugin Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0") public: + virtual void initializeEngine(QQmlEngine *engine, const char *uri) + { + Q_UNUSED(uri); + engine->addImageProvider(QQuickWebEngineFaviconProvider::identifier(), new QQuickWebEngineFaviconProvider); + } + virtual void registerTypes(const char *uri) Q_DECL_OVERRIDE { Q_ASSERT(QLatin1String(uri) == QLatin1String("QtWebEngine")); diff --git a/src/webengine/webengine.pro b/src/webengine/webengine.pro index e4b274a82..236881958 100644 --- a/src/webengine/webengine.pro +++ b/src/webengine/webengine.pro @@ -15,6 +15,7 @@ SOURCES = \ api/qquickwebenginecontextmenudata.cpp \ api/qquickwebenginedownloaditem.cpp \ api/qquickwebenginehistory.cpp \ + api/qquickwebenginefaviconprovider.cpp \ api/qquickwebengineloadrequest.cpp \ api/qquickwebenginenavigationrequest.cpp \ api/qquickwebenginenewviewrequest.cpp \ @@ -36,6 +37,7 @@ HEADERS = \ api/qquickwebenginedownloaditem_p.h \ api/qquickwebenginedownloaditem_p_p.h \ api/qquickwebenginehistory_p.h \ + api/qquickwebenginefaviconprovider_p_p.h \ api/qquickwebengineloadrequest_p.h \ api/qquickwebenginenavigationrequest_p.h \ api/qquickwebenginenewviewrequest_p.h \ diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index 8ba6c8770..447c53ba9 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -484,7 +484,7 @@ void QWebEnginePagePrivate::setFullScreenMode(bool fullscreen) } } -BrowserContextAdapter *QWebEnginePagePrivate::browserContextAdapter() +QSharedPointer<BrowserContextAdapter> QWebEnginePagePrivate::browserContextAdapter() { return profile->d_ptr->browserContext(); } @@ -815,6 +815,10 @@ QAction *QWebEnginePage::action(WebAction action) const text = tr("Reload"); icon = style->standardIcon(QStyle::SP_BrowserReload); break; + case ReloadAndBypassCache: + text = tr("Reload and Bypass Cache"); + icon = style->standardIcon(QStyle::SP_BrowserReload); + break; case Cut: text = tr("Cut"); break; @@ -896,7 +900,9 @@ QAction *QWebEnginePage::action(WebAction action) const case SavePage: text = tr("Save &Page"); break; - default: + case NoWebAction: + case WebActionCount: + Q_UNREACHABLE(); break; } @@ -1084,8 +1090,11 @@ void QWebEnginePage::triggerAction(WebAction action, bool) case SavePage: d->adapter->save(); break; - default: + case NoWebAction: + break; + case WebActionCount: Q_UNREACHABLE(); + break; } } @@ -1157,11 +1166,10 @@ bool QWebEnginePagePrivate::contextMenuRequested(const WebEngineContextMenuData QMenu::exec(view->actions(), event.globalPos(), 0, view); break; } - // fall through - default: + // fallthrough + case Qt::NoContextMenu: event.ignore(); return false; - break; } view->d_func()->m_pendingContextMenuEvent = false; return true; @@ -1210,8 +1218,6 @@ void QWebEnginePagePrivate::javascriptDialog(QSharedPointer<JavaScriptDialogCont case InternalAuthorizationDialog: accepted = (QMessageBox::question(view, controller->title(), controller->message(), QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes); break; - default: - Q_UNREACHABLE(); } if (accepted) controller->accept(); @@ -1397,7 +1403,7 @@ void QWebEnginePage::setFeaturePermission(const QUrl &securityOrigin, QWebEngine else d->adapter->grantMouseLockPermission(false); break; - default: + case Notifications: break; } } @@ -1603,7 +1609,6 @@ QStringList QWebEnginePage::chooseFiles(FileSelectionMode mode, const QStringLis if (!str.isNull()) ret << str; break; - default: case FilePickerController::Open: str = QFileDialog::getOpenFileName(view(), QString(), oldFiles.first()); if (!str.isNull()) diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h index 58515bfbe..22bfaff95 100644 --- a/src/webenginewidgets/api/qwebenginepage_p.h +++ b/src/webenginewidgets/api/qwebenginepage_p.h @@ -136,7 +136,7 @@ public: void startDragging(const content::DropData &dropData, Qt::DropActions allowedActions, const QPixmap &pixmap, const QPoint &offset) Q_DECL_OVERRIDE; - virtual QtWebEngineCore::BrowserContextAdapter *browserContextAdapter() Q_DECL_OVERRIDE; + virtual QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContextAdapter() Q_DECL_OVERRIDE; QtWebEngineCore::WebContentsAdapter *webContentsAdapter() Q_DECL_OVERRIDE; void updateAction(QWebEnginePage::WebAction) const; diff --git a/src/webenginewidgets/api/qwebengineprofile.cpp b/src/webenginewidgets/api/qwebengineprofile.cpp index 3a2254427..2dab0aa08 100644 --- a/src/webenginewidgets/api/qwebengineprofile.cpp +++ b/src/webenginewidgets/api/qwebengineprofile.cpp @@ -140,7 +140,7 @@ using QtWebEngineCore::BrowserContextAdapter; \sa QWebEngineDownloadItem */ -QWebEngineProfilePrivate::QWebEngineProfilePrivate(BrowserContextAdapter* browserContext) +QWebEngineProfilePrivate::QWebEngineProfilePrivate(QSharedPointer<BrowserContextAdapter> browserContext) : m_settings(new QWebEngineSettings()) , m_scriptCollection(new QWebEngineScriptCollection(new QWebEngineScriptCollectionPrivate(browserContext->userResourceController()))) , m_browserContextRef(browserContext) @@ -235,7 +235,7 @@ void QWebEngineProfilePrivate::downloadUpdated(const DownloadItemInfo &info) */ QWebEngineProfile::QWebEngineProfile(QObject *parent) : QObject(parent) - , d_ptr(new QWebEngineProfilePrivate(new BrowserContextAdapter(true))) + , d_ptr(new QWebEngineProfilePrivate(QSharedPointer<BrowserContextAdapter>::create(true))) { d_ptr->q_ptr = this; } @@ -252,7 +252,7 @@ QWebEngineProfile::QWebEngineProfile(QObject *parent) */ QWebEngineProfile::QWebEngineProfile(const QString &storageName, QObject *parent) : QObject(parent) - , d_ptr(new QWebEngineProfilePrivate(new BrowserContextAdapter(storageName))) + , d_ptr(new QWebEngineProfilePrivate(QSharedPointer<BrowserContextAdapter>::create(storageName))) { d_ptr->q_ptr = this; } @@ -712,8 +712,7 @@ void QWebEngineProfile::removeUrlScheme(const QByteArray &scheme) void QWebEngineProfile::removeAllUrlSchemeHandlers() { Q_D(QWebEngineProfile); - d->browserContext()->customUrlSchemeHandlers().clear(); - d->browserContext()->updateCustomUrlSchemeHandlers(); + d->browserContext()->clearCustomUrlSchemeHandlers(); } void QWebEngineProfile::destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler *obj) diff --git a/src/webenginewidgets/api/qwebengineprofile_p.h b/src/webenginewidgets/api/qwebengineprofile_p.h index 9809da42e..4d31c5a81 100644 --- a/src/webenginewidgets/api/qwebengineprofile_p.h +++ b/src/webenginewidgets/api/qwebengineprofile_p.h @@ -57,6 +57,7 @@ #include <QMap> #include <QPointer> #include <QScopedPointer> +#include <QSharedPointer> namespace QtWebEngineCore { class BrowserContextAdapter; @@ -69,10 +70,10 @@ class QWebEngineSettings; class QWebEngineProfilePrivate : public QtWebEngineCore::BrowserContextAdapterClient { public: Q_DECLARE_PUBLIC(QWebEngineProfile) - QWebEngineProfilePrivate(QtWebEngineCore::BrowserContextAdapter* browserContext); + QWebEngineProfilePrivate(QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext); ~QWebEngineProfilePrivate(); - QtWebEngineCore::BrowserContextAdapter *browserContext() const { return m_browserContextRef.data(); } + QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext() const { return m_browserContextRef; } QWebEngineSettings *settings() const { return m_settings; } void cancelDownload(quint32 downloadId); @@ -85,7 +86,7 @@ private: QWebEngineProfile *q_ptr; QWebEngineSettings *m_settings; QScopedPointer<QWebEngineScriptCollection> m_scriptCollection; - QExplicitlySharedDataPointer<QtWebEngineCore::BrowserContextAdapter> m_browserContextRef; + QSharedPointer<QtWebEngineCore::BrowserContextAdapter> m_browserContextRef; QMap<quint32, QPointer<QWebEngineDownloadItem> > m_ongoingDownloads; }; diff --git a/src/webenginewidgets/api/qwebenginesettings.cpp b/src/webenginewidgets/api/qwebenginesettings.cpp index d1caa4ca5..dfca16287 100644 --- a/src/webenginewidgets/api/qwebenginesettings.cpp +++ b/src/webenginewidgets/api/qwebenginesettings.cpp @@ -83,8 +83,6 @@ static WebEngineSettings::Attribute toWebEngineAttribute(QWebEngineSettings::Web return WebEngineSettings::ScreenCaptureEnabled; case QWebEngineSettings::WebGLEnabled: return WebEngineSettings::WebGLEnabled; - case QWebEngineSettings::WebAudioEnabled: - return WebEngineSettings::WebAudioEnabled; case QWebEngineSettings::Accelerated2dCanvasEnabled: return WebEngineSettings::Accelerated2dCanvasEnabled; case QWebEngineSettings::AutoLoadIconsForPage: diff --git a/src/webenginewidgets/api/qwebenginesettings.h b/src/webenginewidgets/api/qwebenginesettings.h index ea18cf020..6dc1b539b 100644 --- a/src/webenginewidgets/api/qwebenginesettings.h +++ b/src/webenginewidgets/api/qwebenginesettings.h @@ -1,22 +1,30 @@ -/* - Copyright (C) 2015 The Qt Company Ltd. - Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) - - 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. -*/ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ #ifndef QWEBENGINESETTINGS_H #define QWEBENGINESETTINGS_H @@ -64,7 +72,6 @@ public: FullScreenSupportEnabled, ScreenCaptureEnabled, WebGLEnabled, - WebAudioEnabled, Accelerated2dCanvasEnabled, AutoLoadIconsForPage, TouchIconsEnabled diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp index add2000d1..396e6950d 100644 --- a/src/webenginewidgets/api/qwebengineview.cpp +++ b/src/webenginewidgets/api/qwebengineview.cpp @@ -86,6 +86,7 @@ void QWebEngineViewPrivate::bind(QWebEngineView *view, QWebEnginePage *page) QObject::connect(page, &QWebEnginePage::titleChanged, view, &QWebEngineView::titleChanged); QObject::connect(page, &QWebEnginePage::urlChanged, view, &QWebEngineView::urlChanged); QObject::connect(page, &QWebEnginePage::iconUrlChanged, view, &QWebEngineView::iconUrlChanged); + QObject::connect(page, &QWebEnginePage::iconChanged, view, &QWebEngineView::iconChanged); QObject::connect(page, &QWebEnginePage::loadStarted, view, &QWebEngineView::loadStarted); QObject::connect(page, &QWebEnginePage::loadProgress, view, &QWebEngineView::loadProgress); QObject::connect(page, &QWebEnginePage::loadFinished, view, &QWebEngineView::loadFinished); @@ -121,6 +122,16 @@ QWebEngineViewPrivate::QWebEngineViewPrivate() with which the process terminated. */ +/*! + \fn void QWebEngineView::iconChanged(const QIcon &icon) + \since 5.7 + + This signal is emitted when the icon ("favicon") associated with the + view is changed. The new icon is specified by \a icon. + + \sa icon(), iconUrl(), iconUrlChanged() +*/ + QWebEngineView::QWebEngineView(QWidget *parent) : QWidget(parent) , d_ptr(new QWebEngineViewPrivate) @@ -198,6 +209,20 @@ QUrl QWebEngineView::iconUrl() const return page()->iconUrl(); } +/*! + \property QWebEngineView::icon + \brief the icon associated with the page currently viewed + \since 5.7 + + By default, this property contains a null icon. + + \sa iconChanged(), iconUrl(), iconUrlChanged() +*/ +QIcon QWebEngineView::icon() const +{ + return page()->icon(); +} + bool QWebEngineView::hasSelection() const { return page()->hasSelection(); diff --git a/src/webenginewidgets/api/qwebengineview.h b/src/webenginewidgets/api/qwebengineview.h index 7181509d2..f7e846861 100644 --- a/src/webenginewidgets/api/qwebengineview.h +++ b/src/webenginewidgets/api/qwebengineview.h @@ -58,7 +58,8 @@ class QWEBENGINEWIDGETS_EXPORT QWebEngineView : public QWidget { Q_OBJECT Q_PROPERTY(QString title READ title) Q_PROPERTY(QUrl url READ url WRITE setUrl) - Q_PROPERTY(QUrl iconUrl READ iconUrl) + Q_PROPERTY(QUrl iconUrl READ iconUrl NOTIFY iconUrlChanged) + Q_PROPERTY(QIcon icon READ icon NOTIFY iconChanged) Q_PROPERTY(QString selectedText READ selectedText) Q_PROPERTY(bool hasSelection READ hasSelection) Q_PROPERTY(qreal zoomFactor READ zoomFactor WRITE setZoomFactor) @@ -80,6 +81,7 @@ public: void setUrl(const QUrl &url); QUrl url() const; QUrl iconUrl() const; + QIcon icon() const; bool hasSelection() const; QString selectedText() const; @@ -116,6 +118,7 @@ Q_SIGNALS: void selectionChanged(); void urlChanged(const QUrl&); void iconUrlChanged(const QUrl&); + void iconChanged(const QIcon&); void renderProcessTerminated(QWebEnginePage::RenderProcessTerminationStatus terminationStatus, int exitCode); diff --git a/src/webenginewidgets/doc/snippets/simple/main.cpp b/src/webenginewidgets/doc/snippets/simple/main.cpp index bebdeff11..666ef3f65 100644 --- a/src/webenginewidgets/doc/snippets/simple/main.cpp +++ b/src/webenginewidgets/doc/snippets/simple/main.cpp @@ -1,21 +1,42 @@ -/* - Copyright (C) 2014 Nokia Corporation and/or its subsidiary(-ies) - - 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. -*/ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ #include <QApplication> #include <QUrl> diff --git a/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc index cb75c69fa..3e0f4cf82 100644 --- a/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc @@ -137,8 +137,6 @@ Enables screen capture in an application. Disabled by default. (Added in Qt 5.7) \value WebGLEnabled Enables support for HTML 5 WebGL. Enabled by default if available. (Added in Qt 5.7) - \value WebAudioEnabled - Enables support for HTML 5 WebAudio. Disabled by default. (Added in Qt 5.7) \value Accelerated2dCanvasEnabled Specifies whether the HTML5 2D canvas should be a OpenGL framebuffer. This makes many painting operations faster, but slows down pixel access. Enabled by default if available. (Added in Qt 5.7) diff --git a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc index 976a1a924..feaa802d7 100644 --- a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc @@ -57,9 +57,11 @@ The title of an HTML document can be accessed with the title() property. Additionally, a web site may specify an icon, which can be accessed - using the iconUrl() property. If the title or the icon changes, the corresponding - titleChanged() and iconUrlChanged() signals will be emitted. The - zoomFactor() property enables zooming the contents of the web page by a scale factor. + using the icon() or its URL using the iconUrl() property. + If the title or the icon changes, the corresponding titleChanged(), iconChanged() + and iconUrlChanged() signals will be emitted. + The zoomFactor() property enables zooming the contents of the web page by a + scale factor. If you require a custom context menu, you can implement it by reimplementing \l{QWidget::}{contextMenuEvent()} and populating your QMenu with the actions @@ -187,9 +189,11 @@ /*! \property QWebEngineView::iconUrl - \brief the URL of the icon associated with the web page currently viewed + \brief the URL of the icon associated with the page currently viewed - \sa iconUrlChanged() + By default, this property contains an empty URL. + + \sa iconUrlChanged(), icon(), iconChanged() */ /*! @@ -329,9 +333,10 @@ /*! \fn void QWebEngineView::iconUrlChanged(const QUrl &url) - This signal is emitted whenever the icon \a url of the view changes. + This signal is emitted when the URL of the icon ("favicon") associated with the + view is changed. The new URL is specified by \a url. - \sa iconUrl() + \sa iconUrl(), icon(), iconChanged() */ /*! diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp index 381a707c2..34170da8a 100644 --- a/tests/auto/quick/publicapi/tst_publicapi.cpp +++ b/tests/auto/quick/publicapi/tst_publicapi.cpp @@ -202,6 +202,155 @@ static QStringList expectedAPI = QStringList() << "QQuickWebEngineView.grantFeaturePermission(QUrl,Feature,bool) --> void" << "QQuickWebEngineView.setActiveFocusOnPress(bool) --> void" << "QQuickWebEngineView.triggerWebAction(WebAction) --> void" + << "QQuickWebEngineView.Unselect --> WebAction" + << "QQuickWebEngineView.SavePage --> WebAction" + << "QQuickWebEngineView.A4 --> PrintedPageSizeId" + << "QQuickWebEngineView.B5 --> PrintedPageSizeId" + << "QQuickWebEngineView.Letter --> PrintedPageSizeId" + << "QQuickWebEngineView.Legal --> PrintedPageSizeId" + << "QQuickWebEngineView.Executive --> PrintedPageSizeId" + << "QQuickWebEngineView.A0 --> PrintedPageSizeId" + << "QQuickWebEngineView.A1 --> PrintedPageSizeId" + << "QQuickWebEngineView.A2 --> PrintedPageSizeId" + << "QQuickWebEngineView.A3 --> PrintedPageSizeId" + << "QQuickWebEngineView.A5 --> PrintedPageSizeId" + << "QQuickWebEngineView.A6 --> PrintedPageSizeId" + << "QQuickWebEngineView.A7 --> PrintedPageSizeId" + << "QQuickWebEngineView.A8 --> PrintedPageSizeId" + << "QQuickWebEngineView.A9 --> PrintedPageSizeId" + << "QQuickWebEngineView.B0 --> PrintedPageSizeId" + << "QQuickWebEngineView.B1 --> PrintedPageSizeId" + << "QQuickWebEngineView.B10 --> PrintedPageSizeId" + << "QQuickWebEngineView.B2 --> PrintedPageSizeId" + << "QQuickWebEngineView.B3 --> PrintedPageSizeId" + << "QQuickWebEngineView.B4 --> PrintedPageSizeId" + << "QQuickWebEngineView.B6 --> PrintedPageSizeId" + << "QQuickWebEngineView.B7 --> PrintedPageSizeId" + << "QQuickWebEngineView.B8 --> PrintedPageSizeId" + << "QQuickWebEngineView.B9 --> PrintedPageSizeId" + << "QQuickWebEngineView.C5E --> PrintedPageSizeId" + << "QQuickWebEngineView.Comm10E --> PrintedPageSizeId" + << "QQuickWebEngineView.DLE --> PrintedPageSizeId" + << "QQuickWebEngineView.Folio --> PrintedPageSizeId" + << "QQuickWebEngineView.Ledger --> PrintedPageSizeId" + << "QQuickWebEngineView.Tabloid --> PrintedPageSizeId" + << "QQuickWebEngineView.Custom --> PrintedPageSizeId" + << "QQuickWebEngineView.A10 --> PrintedPageSizeId" + << "QQuickWebEngineView.A3Extra --> PrintedPageSizeId" + << "QQuickWebEngineView.A4Extra --> PrintedPageSizeId" + << "QQuickWebEngineView.A4Plus --> PrintedPageSizeId" + << "QQuickWebEngineView.A4Small --> PrintedPageSizeId" + << "QQuickWebEngineView.A5Extra --> PrintedPageSizeId" + << "QQuickWebEngineView.B5Extra --> PrintedPageSizeId" + << "QQuickWebEngineView.JisB0 --> PrintedPageSizeId" + << "QQuickWebEngineView.JisB1 --> PrintedPageSizeId" + << "QQuickWebEngineView.JisB2 --> PrintedPageSizeId" + << "QQuickWebEngineView.JisB3 --> PrintedPageSizeId" + << "QQuickWebEngineView.JisB4 --> PrintedPageSizeId" + << "QQuickWebEngineView.JisB5 --> PrintedPageSizeId" + << "QQuickWebEngineView.JisB6 --> PrintedPageSizeId" + << "QQuickWebEngineView.JisB7 --> PrintedPageSizeId" + << "QQuickWebEngineView.JisB8 --> PrintedPageSizeId" + << "QQuickWebEngineView.JisB9 --> PrintedPageSizeId" + << "QQuickWebEngineView.JisB10 --> PrintedPageSizeId" + << "QQuickWebEngineView.AnsiC --> PrintedPageSizeId" + << "QQuickWebEngineView.AnsiD --> PrintedPageSizeId" + << "QQuickWebEngineView.AnsiE --> PrintedPageSizeId" + << "QQuickWebEngineView.LegalExtra --> PrintedPageSizeId" + << "QQuickWebEngineView.LetterExtra --> PrintedPageSizeId" + << "QQuickWebEngineView.LetterPlus --> PrintedPageSizeId" + << "QQuickWebEngineView.LetterSmall --> PrintedPageSizeId" + << "QQuickWebEngineView.TabloidExtra --> PrintedPageSizeId" + << "QQuickWebEngineView.ArchA --> PrintedPageSizeId" + << "QQuickWebEngineView.ArchB --> PrintedPageSizeId" + << "QQuickWebEngineView.ArchC --> PrintedPageSizeId" + << "QQuickWebEngineView.ArchD --> PrintedPageSizeId" + << "QQuickWebEngineView.ArchE --> PrintedPageSizeId" + << "QQuickWebEngineView.Imperial7x9 --> PrintedPageSizeId" + << "QQuickWebEngineView.Imperial8x10 --> PrintedPageSizeId" + << "QQuickWebEngineView.Imperial9x11 --> PrintedPageSizeId" + << "QQuickWebEngineView.Imperial9x12 --> PrintedPageSizeId" + << "QQuickWebEngineView.Imperial10x11 --> PrintedPageSizeId" + << "QQuickWebEngineView.Imperial10x13 --> PrintedPageSizeId" + << "QQuickWebEngineView.Imperial10x14 --> PrintedPageSizeId" + << "QQuickWebEngineView.Imperial12x11 --> PrintedPageSizeId" + << "QQuickWebEngineView.Imperial15x11 --> PrintedPageSizeId" + << "QQuickWebEngineView.ExecutiveStandard --> PrintedPageSizeId" + << "QQuickWebEngineView.Note --> PrintedPageSizeId" + << "QQuickWebEngineView.Quarto --> PrintedPageSizeId" + << "QQuickWebEngineView.Statement --> PrintedPageSizeId" + << "QQuickWebEngineView.SuperA --> PrintedPageSizeId" + << "QQuickWebEngineView.SuperB --> PrintedPageSizeId" + << "QQuickWebEngineView.Postcard --> PrintedPageSizeId" + << "QQuickWebEngineView.DoublePostcard --> PrintedPageSizeId" + << "QQuickWebEngineView.Prc16K --> PrintedPageSizeId" + << "QQuickWebEngineView.Prc32K --> PrintedPageSizeId" + << "QQuickWebEngineView.Prc32KBig --> PrintedPageSizeId" + << "QQuickWebEngineView.FanFoldUS --> PrintedPageSizeId" + << "QQuickWebEngineView.FanFoldGerman --> PrintedPageSizeId" + << "QQuickWebEngineView.FanFoldGermanLegal --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopeB4 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopeB5 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopeB6 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopeC0 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopeC1 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopeC2 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopeC3 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopeC4 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopeC6 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopeC65 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopeC7 --> PrintedPageSizeId" + << "QQuickWebEngineView.Envelope9 --> PrintedPageSizeId" + << "QQuickWebEngineView.Envelope11 --> PrintedPageSizeId" + << "QQuickWebEngineView.Envelope12 --> PrintedPageSizeId" + << "QQuickWebEngineView.Envelope14 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopeMonarch --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopePersonal --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopeChou3 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopeChou4 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopeInvite --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopeItalian --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopeKaku2 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopeKaku3 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopePrc1 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopePrc2 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopePrc3 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopePrc4 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopePrc5 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopePrc6 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopePrc7 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopePrc8 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopePrc9 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopePrc10 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopeYou4 --> PrintedPageSizeId" + << "QQuickWebEngineView.LastPageSize --> PrintedPageSizeId" + << "QQuickWebEngineView.NPageSize --> PrintedPageSizeId" + << "QQuickWebEngineView.NPaperSize --> PrintedPageSizeId" + << "QQuickWebEngineView.AnsiA --> PrintedPageSizeId" + << "QQuickWebEngineView.AnsiB --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopeC5 --> PrintedPageSizeId" + << "QQuickWebEngineView.EnvelopeDL --> PrintedPageSizeId" + << "QQuickWebEngineView.Envelope10 --> PrintedPageSizeId" + << "QQuickWebEngineView.Portrait --> PrintedPageOrientation" + << "QQuickWebEngineView.Landscape --> PrintedPageOrientation" + << "QQuickWebEngineView.contentsSize --> QSizeF" + << "QQuickWebEngineView.scrollPosition --> QPointF" + << "QQuickWebEngineView.audioMuted --> bool" + << "QQuickWebEngineView.recentlyAudible --> bool" + << "QQuickWebEngineView.webChannelWorld --> uint" + << "QQuickWebEngineView.contentsSizeChanged(QSizeF) --> void" + << "QQuickWebEngineView.scrollPositionChanged(QPointF) --> void" + << "QQuickWebEngineView.audioMutedChanged(bool) --> void" + << "QQuickWebEngineView.recentlyAudibleChanged(bool) --> void" + << "QQuickWebEngineView.webChannelWorldChanged(uint) --> void" + << "QQuickWebEngineView.runJavaScript(QString,uint,QJSValue) --> void" + << "QQuickWebEngineView.runJavaScript(QString,uint) --> void" + << "QQuickWebEngineView.printToPdf(QString,PrintedPageSizeId,PrintedPageOrientation) --> void" + << "QQuickWebEngineView.printToPdf(QString,PrintedPageSizeId) --> void" + << "QQuickWebEngineView.printToPdf(QString) --> void" + << "QQuickWebEngineView.printToPdf(QJSValue,PrintedPageSizeId,PrintedPageOrientation) --> void" + << "QQuickWebEngineView.printToPdf(QJSValue,PrintedPageSizeId) --> void" + << "QQuickWebEngineView.printToPdf(QJSValue) --> void" << "QQuickWebEngineCertificateError.SslPinnedKeyNotInCertificateChain --> Error" << "QQuickWebEngineCertificateError.CertificateCommonNameInvalid --> Error" << "QQuickWebEngineCertificateError.CertificateDateInvalid --> Error" @@ -240,6 +389,12 @@ static QStringList expectedAPI = QStringList() << "QQuickWebEngineDownloadItem.pathChanged() --> void" << "QQuickWebEngineDownloadItem.accept() --> void" << "QQuickWebEngineDownloadItem.cancel() --> void" + << "QQuickWebEngineDownloadItem.UnknownSaveFormat --> SavePageFormat" + << "QQuickWebEngineDownloadItem.SingleHtmlSaveFormat --> SavePageFormat" + << "QQuickWebEngineDownloadItem.CompleteHtmlSaveFormat --> SavePageFormat" + << "QQuickWebEngineDownloadItem.MimeHtmlSaveFormat --> SavePageFormat" + << "QQuickWebEngineDownloadItem.savePageFormat --> SavePageFormat" + << "QQuickWebEngineDownloadItem.savePageFormatChanged() --> void" << "QQuickWebEngineHistory.items --> QQuickWebEngineHistoryListModel*" << "QQuickWebEngineHistory.backItems --> QQuickWebEngineHistoryListModel*" << "QQuickWebEngineHistory.forwardItems --> QQuickWebEngineHistoryListModel*" @@ -281,6 +436,7 @@ static QStringList expectedAPI = QStringList() << "QQuickWebEngineProfile.httpAcceptLanguageChanged() --> void" << "QQuickWebEngineProfile.downloadRequested(QQuickWebEngineDownloadItem*) --> void" << "QQuickWebEngineProfile.downloadFinished(QQuickWebEngineDownloadItem*) --> void" + << "QQuickWebEngineProfile.NoCache --> HttpCacheType" << "QQuickWebEngineScript.Deferred --> InjectionPoint" << "QQuickWebEngineScript.DocumentReady --> InjectionPoint" << "QQuickWebEngineScript.DocumentCreation --> InjectionPoint" @@ -334,6 +490,18 @@ static QStringList expectedAPI = QStringList() << "QQuickWebEngineSettings.pluginsEnabledChanged() --> void" << "QQuickWebEngineSettings.fullScreenSupportEnabledChanged() --> void" << "QQuickWebEngineSettings.defaultTextEncodingChanged() --> void" + << "QQuickWebEngineSettings.screenCaptureEnabled --> bool" + << "QQuickWebEngineSettings.webGLEnabled --> bool" + << "QQuickWebEngineSettings.webAudioEnabled --> bool" + << "QQuickWebEngineSettings.accelerated2dCanvasEnabled --> bool" + << "QQuickWebEngineSettings.autoLoadIconsForPage --> bool" + << "QQuickWebEngineSettings.touchIconsEnabled --> bool" + << "QQuickWebEngineSettings.screenCaptureEnabledChanged() --> void" + << "QQuickWebEngineSettings.webGLEnabledChanged() --> void" + << "QQuickWebEngineSettings.webAudioEnabledChanged() --> void" + << "QQuickWebEngineSettings.accelerated2dCanvasEnabledChanged() --> void" + << "QQuickWebEngineSettings.autoLoadIconsForPageChanged() --> void" + << "QQuickWebEngineSettings.touchIconsEnabledChanged() --> void" << "QQuickWebEngineFullScreenRequest.origin --> QUrl" << "QQuickWebEngineFullScreenRequest.toggleOn --> bool" << "QQuickWebEngineFullScreenRequest.accept() --> void" diff --git a/tests/auto/quick/qmltests/data/favicon-multi-gray.html b/tests/auto/quick/qmltests/data/favicon-multi-gray.html new file mode 100644 index 000000000..d6ac0909f --- /dev/null +++ b/tests/auto/quick/qmltests/data/favicon-multi-gray.html @@ -0,0 +1,9 @@ +<html> + <head> + <title>Gray Multi-sized Favicon Test</title> + <link rel="shortcut icon" href="icons/grayicons.ico" /> + </head> + <body> + <h1>Gray Multi-sized Favicon Test</h1> + </body> +</html> diff --git a/tests/auto/quick/qmltests/data/icons/grayicons.ico b/tests/auto/quick/qmltests/data/icons/grayicons.ico Binary files differnew file mode 100644 index 000000000..8d8fee839 --- /dev/null +++ b/tests/auto/quick/qmltests/data/icons/grayicons.ico diff --git a/tests/auto/quick/qmltests/data/localStorage.html b/tests/auto/quick/qmltests/data/localStorage.html new file mode 100644 index 000000000..a4e395f48 --- /dev/null +++ b/tests/auto/quick/qmltests/data/localStorage.html @@ -0,0 +1,9 @@ +<html> +<head><title>Original Title</title></head> +<body> +<script type="text/javascript"> +document.title = localStorage.getItem('title'); +localStorage.setItem('title', 'New Title'); +</script> +</body> +</html> diff --git a/tests/auto/quick/qmltests/data/tst_favicon.qml b/tests/auto/quick/qmltests/data/tst_favicon.qml index 26e39f48c..e959f19be 100644 --- a/tests/auto/quick/qmltests/data/tst_favicon.qml +++ b/tests/auto/quick/qmltests/data/tst_favicon.qml @@ -50,6 +50,10 @@ TestWebEngineView { } } + function removeFaviconProviderPrefix(url) { + return url.toString().substring(16) + } + SignalSpy { id: iconChangedSpy target: webEngineView @@ -64,6 +68,7 @@ TestWebEngineView { TestCase { id: test name: "WebEngineFavicon" + when: windowShown function init() { if (webEngineView.icon != '') { @@ -185,7 +190,7 @@ TestWebEngineView { iconChangedSpy.wait() compare(iconChangedSpy.count, 1) - iconUrl = webEngineView.icon + iconUrl = removeFaviconProviderPrefix(webEngineView.icon) // Touch icon is ignored compare(iconUrl, Qt.resolvedUrl("icons/qt32.ico")) compare(favicon.width, 32) @@ -199,13 +204,13 @@ TestWebEngineView { iconChangedSpy.wait() verify(iconChangedSpy.count >= 1) - iconUrl = webEngineView.icon + iconUrl = removeFaviconProviderPrefix(webEngineView.icon) // If the icon URL is empty we have to wait for // the second iconChanged signal that propagates the expected URL if (iconUrl == Qt.resolvedUrl("")) { tryCompare(iconChangedSpy, "count", 2) - iconUrl = webEngineView.icon + iconUrl = removeFaviconProviderPrefix(webEngineView.icon) } compare(iconUrl, Qt.resolvedUrl("icons/qt144.png")) @@ -224,6 +229,21 @@ TestWebEngineView { var iconUrl = webEngineView.icon compare(iconUrl, Qt.resolvedUrl("")) + compare(favicon.width, 0) + compare(favicon.height, 0) + + WebEngine.settings.touchIconsEnabled = true + + url = Qt.resolvedUrl("favicon-touch.html") + webEngineView.url = url + verify(webEngineView.waitForLoadSucceeded()) + + iconChangedSpy.wait() + iconUrl = removeFaviconProviderPrefix(webEngineView.icon) + compare(iconUrl, Qt.resolvedUrl("icons/qt144.png")) + compare(iconChangedSpy.count, 1) + compare(favicon.width, 144) + compare(favicon.height, 144) } function test_multiIcon() { @@ -235,11 +255,69 @@ TestWebEngineView { iconChangedSpy.wait() compare(iconChangedSpy.count, 1) + compare(favicon.width, 64) + compare(favicon.height, 64) + } - // Image QML type does not support multi-sized icons thus - // chooses the first size - compare(favicon.width, 16) - compare(favicon.height, 16) + function test_faviconProvider_data() { + return [ + { tag: "8x8", size: 8, value: 16 }, + { tag: "16x16", size: 16, value: 16 }, + { tag: "17x17", size: 17, value: 32 }, + { tag: "31x31", size: 31, value: 32 }, + { tag: "32x32", size: 32, value: 32 }, + { tag: "33x33", size: 33, value: 64 }, + { tag: "64x64", size: 64, value: 64 }, + { tag: "128x128", size: 128, value: 128 }, + { tag: "255x255", size: 255, value: 255 }, + { tag: "256x256", size: 256, value: 255 }, + ]; + } + + function test_faviconProvider(row) { + var faviconImage = Qt.createQmlObject(" + import QtQuick 2.5\n + Image { sourceSize: Qt.size(width, height) }", test) + var grabImage = Qt.createQmlObject(" + import QtQuick 2.5\n + Image { }", test) + var faviconCanvas = Qt.createQmlObject(" + import QtQuick 2.5\n + Canvas { }", test) + + compare(iconChangedSpy.count, 0) + + var url = Qt.resolvedUrl("favicon-multi-gray.html") + webEngineView.url = url + verify(webEngineView.waitForLoadSucceeded()) + + iconChangedSpy.wait() + compare(iconChangedSpy.count, 1) + + faviconImage.width = row.size + faviconImage.height = row.size + faviconImage.source = webEngineView.icon + verify(_waitFor(function() { return faviconImage.status == Image.Ready } )) + + faviconImage.grabToImage(function(result) { + grabImage.source = result.url + }) + verify(_waitFor(function() { return grabImage.status == Image.Ready } )) + + faviconCanvas.width = faviconImage.width + faviconCanvas.height = faviconImage.height + var ctx = faviconCanvas.getContext("2d") + ctx.drawImage(grabImage, 0, 0, grabImage.width, grabImage.height) + + var center = Math.round(row.size/2) + var imageData = ctx.getImageData(center, center, center, center) + var pixel = imageData.data + + compare(pixel[0], row.value) + + faviconImage.destroy() + grabImage.destroy() + faviconCanvas.destroy() } } } diff --git a/tests/auto/quick/qmltests/data/tst_faviconDownload.qml b/tests/auto/quick/qmltests/data/tst_faviconDownload.qml index e4dfb36aa..406dfa3ea 100644 --- a/tests/auto/quick/qmltests/data/tst_faviconDownload.qml +++ b/tests/auto/quick/qmltests/data/tst_faviconDownload.qml @@ -35,6 +35,10 @@ TestWebEngineView { width: 200 height: 400 + function removeFaviconProviderPrefix(url) { + return url.toString().substring(16) + } + SignalSpy { id: iconChangedSpy target: webEngineView @@ -108,7 +112,7 @@ TestWebEngineView { iconChangedSpy.wait() compare(iconChangedSpy.count, 1) - var iconUrl = webEngineView.icon + var iconUrl = removeFaviconProviderPrefix(webEngineView.icon) compare(iconUrl, row.expectedIconUrl) } } diff --git a/tests/auto/quick/qmltests/data/tst_settings.qml b/tests/auto/quick/qmltests/data/tst_settings.qml new file mode 100644 index 000000000..aa3a6dc60 --- /dev/null +++ b/tests/auto/quick/qmltests/data/tst_settings.qml @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtWebEngine 1.2 + +TestWebEngineView { + id: webEngineView + width: 400 + height: 300 + + TestCase { + name: "WebEngineViewSettings" + + function test_javascriptEnabled() { + webEngineView.settings.javascriptEnabled = true; + + webEngineView.url = Qt.resolvedUrl("javascript.html"); + verify(webEngineView.waitForLoadSucceeded()); + compare(webEngineView.title, "New Title"); + } + + function test_javascriptDisabled() { + webEngineView.settings.javascriptEnabled = false; + + webEngineView.url = Qt.resolvedUrl("javascript.html"); + verify(webEngineView.waitForLoadSucceeded()); + compare(webEngineView.title, "Original Title"); + } + + function test_localStorageDisabled() { + webEngineView.settings.javascriptEnabled = true; + webEngineView.settings.localStorageEnabled = false; + + webEngineView.url = Qt.resolvedUrl("localStorage.html"); + verify(webEngineView.waitForLoadSucceeded()); + compare(webEngineView.title, "Original Title"); + } + + function test_localStorageEnabled() { + webEngineView.settings.localStorageEnabled = true; + webEngineView.settings.javascriptEnabled = true; + + webEngineView.url = Qt.resolvedUrl("localStorage.html"); + verify(webEngineView.waitForLoadSucceeded()); + webEngineView.reload(); + verify(webEngineView.waitForLoadSucceeded()); + compare(webEngineView.title, "New Title"); + } + + function test_settingsAffectCurrentViewOnly() { + var webEngineView2 = Qt.createQmlObject('TestWebEngineView {width: 400; height: 300;}', webEngineView); + + webEngineView.settings.javascriptEnabled = true; + webEngineView2.settings.javascriptEnabled = true; + + var testUrl = Qt.resolvedUrl("javascript.html"); + + webEngineView.url = testUrl; + verify(webEngineView.waitForLoadSucceeded()); + webEngineView2.url = testUrl; + verify(webEngineView2.waitForLoadSucceeded()); + + compare(webEngineView.title, "New Title"); + compare(webEngineView2.title, "New Title"); + + webEngineView.settings.javascriptEnabled = false; + + webEngineView.url = testUrl; + verify(webEngineView.waitForLoadSucceeded()); + webEngineView2.url = testUrl; + verify(webEngineView2.waitForLoadSucceeded()); + + compare(webEngineView.title, "Original Title"); + compare(webEngineView2.title, "New Title"); + + webEngineView2.destroy(); + } + } +} + diff --git a/tests/auto/quick/qmltests/qmltests.pro b/tests/auto/quick/qmltests/qmltests.pro index 257c1c4f6..b8f0f7df1 100644 --- a/tests/auto/quick/qmltests/qmltests.pro +++ b/tests/auto/quick/qmltests/qmltests.pro @@ -18,6 +18,7 @@ OTHER_FILES += \ $$PWD/data/favicon2.html \ $$PWD/data/favicon-misc.html \ $$PWD/data/favicon-multi.html \ + $$PWD/data/favicon-multi-gray.html \ $$PWD/data/favicon-single.html \ $$PWD/data/favicon-shortcut.html \ $$PWD/data/favicon-touch.html \ @@ -26,6 +27,7 @@ OTHER_FILES += \ $$PWD/data/geolocation.html \ $$PWD/data/javascript.html \ $$PWD/data/link.html \ + $$PWD/data/localStorage.html \ $$PWD/data/prompt.html \ $$PWD/data/multifileupload.html \ $$PWD/data/redirect.html \ @@ -60,8 +62,10 @@ OTHER_FILES += \ $$PWD/data/tst_unhandledKeyEventPropagation.qml \ $$PWD/data/tst_userScripts.qml \ $$PWD/data/tst_webchannel.qml \ + $$PWD/data/tst_settings.qml \ $$PWD/data/tst_keyboardModifierMapping.qml \ $$PWD/data/icons/favicon.png \ + $$PWD/data/icons/grayicons.ico \ $$PWD/data/icons/small-favicon.png \ $$PWD/data/icons/qt144.png \ $$PWD/data/icons/qt32.ico \ diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp index f2f5b31f9..0def76d6f 100644 --- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp +++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp @@ -1,21 +1,30 @@ -/* - Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies) - - 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. -*/ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ #include "testwindow.h" #include "util.h" @@ -60,6 +69,7 @@ private Q_SLOTS: void inputMethod(); void inputMethodHints(); void basicRenderingSanity(); + void setZoomFactor(); void printToPdf(); private: @@ -462,6 +472,25 @@ void tst_QQuickWebEngineView::inputMethodHints() #endif } +void tst_QQuickWebEngineView::setZoomFactor() +{ + QQuickWebEngineView *view = webEngineView(); + + QVERIFY(qFuzzyCompare(view->zoomFactor(), 1.0)); + view->setZoomFactor(2.5); + QVERIFY(qFuzzyCompare(view->zoomFactor(), 2.5)); + + view->setUrl(urlFromTestPath("html/basic_page.html")); + QVERIFY(waitForLoadSucceeded(view)); + QVERIFY(qFuzzyCompare(view->zoomFactor(), 2.5)); + + view->setZoomFactor(0.1); + QVERIFY(qFuzzyCompare(view->zoomFactor(), 2.5)); + + view->setZoomFactor(5.5); + QVERIFY(qFuzzyCompare(view->zoomFactor(), 2.5)); +} + void tst_QQuickWebEngineView::printToPdf() { QTemporaryDir tempDir(QDir::tempPath() + "/tst_qwebengineview-XXXXXX"); diff --git a/tests/auto/quick/shared/testwindow.h b/tests/auto/quick/shared/testwindow.h index f5181ee97..b57443c69 100644 --- a/tests/auto/quick/shared/testwindow.h +++ b/tests/auto/quick/shared/testwindow.h @@ -1,21 +1,30 @@ -/* - Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies) - - 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. -*/ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ #ifndef TESTWINDOW_H #define TESTWINDOW_H diff --git a/tests/auto/quick/shared/util.h b/tests/auto/quick/shared/util.h index 66b42d010..063caa766 100644 --- a/tests/auto/quick/shared/util.h +++ b/tests/auto/quick/shared/util.h @@ -1,21 +1,30 @@ -/* - Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies) - - 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. -*/ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ #ifndef UTIL_H #define UTIL_H diff --git a/tests/auto/widgets/qwebengineinspector/tst_qwebengineinspector.cpp b/tests/auto/widgets/qwebengineinspector/tst_qwebengineinspector.cpp index 8d7e41f0f..000214b9a 100644 --- a/tests/auto/widgets/qwebengineinspector/tst_qwebengineinspector.cpp +++ b/tests/auto/widgets/qwebengineinspector/tst_qwebengineinspector.cpp @@ -1,21 +1,30 @@ -/* - Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) - - 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. -*/ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ #include <QtTest/QtTest> diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index e42af77c2..cc9b1838c 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2016 The Qt Company Ltd. Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in> Copyright (C) 2010 Holger Hans Peter Freyther @@ -236,6 +236,7 @@ private Q_SLOTS: void restoreHistory(); void toPlainTextLoadFinishedRace_data(); void toPlainTextLoadFinishedRace(); + void setZoomFactor(); void printToPdf(); @@ -4966,6 +4967,31 @@ void tst_QWebEnginePage::toPlainTextLoadFinishedRace() QVERIFY(spy.count() == 3); } +void tst_QWebEnginePage::setZoomFactor() +{ + QWebEnginePage *page = new QWebEnginePage; + + QVERIFY(qFuzzyCompare(page->zoomFactor(), 1.0)); + page->setZoomFactor(2.5); + QVERIFY(qFuzzyCompare(page->zoomFactor(), 2.5)); + + const QUrl urlToLoad("qrc:/resources/test1.html"); + + QSignalSpy finishedSpy(m_page, SIGNAL(loadFinished(bool))); + m_page->setUrl(urlToLoad); + QTRY_COMPARE(finishedSpy.count(), 1); + QVERIFY(finishedSpy.at(0).first().toBool()); + QVERIFY(qFuzzyCompare(page->zoomFactor(), 2.5)); + + page->setZoomFactor(5.5); + QVERIFY(qFuzzyCompare(page->zoomFactor(), 2.5)); + + page->setZoomFactor(0.1); + QVERIFY(qFuzzyCompare(page->zoomFactor(), 2.5)); + + delete page; +} + void tst_QWebEnginePage::printToPdf() { QTemporaryDir tempDir(QDir::tempPath() + "/tst_qwebengineview-XXXXXX"); diff --git a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp index e73ab637b..95d5cf16a 100644 --- a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp +++ b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp @@ -47,6 +47,8 @@ private Q_SLOTS: void disableCache(); void urlSchemeHandlers(); void urlSchemeHandlerFailRequest(); + void customUserAgent(); + void httpAcceptLanguage(); }; void tst_QWebEngineProfile::defaultProfile() @@ -253,5 +255,60 @@ void tst_QWebEngineProfile::urlSchemeHandlerFailRequest() QCOMPARE(toPlainTextSync(view.page()), QString()); } +void tst_QWebEngineProfile::customUserAgent() +{ + QString defaultUserAgent = QWebEngineProfile::defaultProfile()->httpUserAgent(); + QWebEnginePage page; + QSignalSpy loadFinishedSpy(&page, SIGNAL(loadFinished(bool))); + page.setHtml(QStringLiteral("<html><body>Hello world!</body></html>")); + QTRY_COMPARE(loadFinishedSpy.count(), 1); + + // First test the user-agent is default + QCOMPARE(evaluateJavaScriptSync(&page, QStringLiteral("navigator.userAgent")).toString(), defaultUserAgent); + + const QString testUserAgent = QStringLiteral("tst_QWebEngineProfile 1.0"); + QWebEngineProfile testProfile; + testProfile.setHttpUserAgent(testUserAgent); + + // Test a new profile with custom user-agent works + QWebEnginePage page2(&testProfile); + QSignalSpy loadFinishedSpy2(&page2, SIGNAL(loadFinished(bool))); + page2.setHtml(QStringLiteral("<html><body>Hello again!</body></html>")); + QTRY_COMPARE(loadFinishedSpy2.count(), 1); + QCOMPARE(evaluateJavaScriptSync(&page2, QStringLiteral("navigator.userAgent")).toString(), testUserAgent); + QCOMPARE(evaluateJavaScriptSync(&page, QStringLiteral("navigator.userAgent")).toString(), defaultUserAgent); + + // Test an existing page and profile with custom user-agent works + QWebEngineProfile::defaultProfile()->setHttpUserAgent(testUserAgent); + QCOMPARE(evaluateJavaScriptSync(&page, QStringLiteral("navigator.userAgent")).toString(), testUserAgent); +} + +void tst_QWebEngineProfile::httpAcceptLanguage() +{ + QWebEnginePage page; + QSignalSpy loadFinishedSpy(&page, SIGNAL(loadFinished(bool))); + page.setHtml(QStringLiteral("<html><body>Hello world!</body></html>")); + QTRY_COMPARE(loadFinishedSpy.count(), 1); + + QStringList defaultLanguages = evaluateJavaScriptSync(&page, QStringLiteral("navigator.languages")).toStringList(); + + const QString testLang = QStringLiteral("xx-YY"); + QWebEngineProfile testProfile; + testProfile.setHttpAcceptLanguage(testLang); + + // Test a completely new profile + QWebEnginePage page2(&testProfile); + QSignalSpy loadFinishedSpy2(&page2, SIGNAL(loadFinished(bool))); + page2.setHtml(QStringLiteral("<html><body>Hello again!</body></html>")); + QTRY_COMPARE(loadFinishedSpy2.count(), 1); + QCOMPARE(evaluateJavaScriptSync(&page2, QStringLiteral("navigator.languages")).toStringList(), QStringList(testLang)); + // Test the old one wasn't affected + QCOMPARE(evaluateJavaScriptSync(&page, QStringLiteral("navigator.languages")).toStringList(), defaultLanguages); + + // Test changing an existing page and profile + QWebEngineProfile::defaultProfile()->setHttpAcceptLanguage(testLang); + QCOMPARE(evaluateJavaScriptSync(&page, QStringLiteral("navigator.languages")).toStringList(), QStringList(testLang)); +} + QTEST_MAIN(tst_QWebEngineProfile) #include "tst_qwebengineprofile.moc" diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index 773550922..8aaf9ccc3 100644 --- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2016 The Qt Company Ltd. Copyright (C) 2009 Torch Mobile Inc. Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in> diff --git a/tests/auto/widgets/util.h b/tests/auto/widgets/util.h index c2c72c8f4..770579f1f 100644 --- a/tests/auto/widgets/util.h +++ b/tests/auto/widgets/util.h @@ -1,21 +1,31 @@ -/* - Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) - - 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. -*/ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + // Functions and macros that really need to be in QTestLib #if 0 diff --git a/tools/qmake/mkspecs/features/configure.prf b/tools/qmake/mkspecs/features/configure.prf index 84ec4d7f0..0dfb67a84 100644 --- a/tools/qmake/mkspecs/features/configure.prf +++ b/tools/qmake/mkspecs/features/configure.prf @@ -90,7 +90,7 @@ defineTest(finalizeConfigure) { skipBuild("Unmet dependencies: icu-uc, icu-i18n") } } else { - log("ICU............................... Using internal copy (Default, force system ICU with WEBENGINE_CONFIG += use_system_icu)$${EOL}") + log("ICU............................... Using internal copy (Default, force system ICU with WEBENGINE_CONFIG+=use_system_icu)$${EOL}") } use?(system_ffmpeg) { packagesExist("libavcodec libavformat libavutil") { @@ -105,13 +105,13 @@ defineTest(finalizeConfigure) { skipBuild("Unmet dependencies: libavcodec, libavformat, libavutil") } } else { - log("FFMPEG............................ Using internal copy (Default, force system FFMPEG with WEBENGINE_CONFIG += use_system_ffmpeg)$${EOL}") + log("FFMPEG............................ Using internal copy (Default, force system FFMPEG with WEBENGINE_CONFIG+=use_system_ffmpeg)$${EOL}") } } use?(proprietary_codecs) { log("Proprietary codecs (H264, MP3).... Enabled$${EOL}") } else { - log("Proprietary codecs (H264, MP3).... Not enabled (Default, enable with WEBENGINE_CONFIG += use_proprietary_codecs)$${EOL}") + log("Proprietary codecs (H264, MP3).... Not enabled (Default, enable with WEBENGINE_CONFIG+=use_proprietary_codecs)$${EOL}") } osx { use?(appstore_compliant_code) { diff --git a/tools/scripts/git_submodule.py b/tools/scripts/git_submodule.py index 9252a9424..fcf2af37a 100644 --- a/tools/scripts/git_submodule.py +++ b/tools/scripts/git_submodule.py @@ -50,6 +50,7 @@ class DEPSParser: 'deps_os': {}, } self.local_scope = {} + self.topmost_supermodule_path_prefix = '' def Lookup(self, var_name): return self.local_scope["vars"][var_name] @@ -64,16 +65,18 @@ class DEPSParser: subdir = dep if subdir.startswith('src/'): subdir = subdir[4:] - else: + # Don't skip submodules that have a supermodule path prefix set (at the moment these + # are 2nd level deep submodules). + elif not self.topmost_supermodule_path_prefix: # Ignore the information about chromium itself since we get that from git, # also ignore anything outside src/ (e.g. depot_tools) continue - submodule = Submodule(subdir, repo) + submodule = Submodule(subdir, repo, sp=self.topmost_supermodule_path_prefix) submodule.os = os if not submodule.matchesOS(): - print '-- skipping ' + submodule.path + ' for this operating system. --' + print '-- skipping ' + submodule.pathRelativeToTopMostSupermodule() + ' for this operating system. --' continue if len(rev) == 40: # Length of a git shasum @@ -88,16 +91,36 @@ class DEPSParser: submodules = [] submodules.extend(self.createSubmodulesFromScope(self.local_scope['deps'], 'all')) - for os_dep in self.local_scope['deps_os']: - submodules.extend(self.createSubmodulesFromScope(self.local_scope['deps_os'][os_dep], os_dep)) + if 'deps_os' in self.local_scope: + for os_dep in self.local_scope['deps_os']: + submodules.extend(self.createSubmodulesFromScope(self.local_scope['deps_os'][os_dep], os_dep)) return submodules +# Strips suffix from end of text. +def strip_end(text, suffix): + if not text.endswith(suffix): + return text + return text[:len(text)-len(suffix)] + +# Given supermodule_path = /chromium +# current directory = /chromium/buildtools +# submodule_path = third_party/foo/bar +# returns = buildtools +def computeRelativePathPrefixToTopMostSupermodule(submodule_path, supermodule_path): + relpath = os.path.relpath(submodule_path, supermodule_path) + topmost_supermodule_path_prefix = strip_end(relpath, submodule_path) + return topmost_supermodule_path_prefix + class Submodule: - def __init__(self, path='', url='', ref='', os=[]): + def __init__(self, path='', url='', ref='', os=[], sp=''): self.path = path self.url = url self.ref = ref self.os = os + self.topmost_supermodule_path_prefix = sp + + def pathRelativeToTopMostSupermodule(self): + return os.path.normpath(os.path.join(self.topmost_supermodule_path_prefix, self.path)) def matchesOS(self): if not self.os: @@ -178,8 +201,14 @@ class Submodule: def initialize(self): if self.matchesOS(): - print '\n\n-- initializing ' + self.path + ' --' + print '\n\n-- initializing ' + self.pathRelativeToTopMostSupermodule() + ' --' oldCwd = os.getcwd() + + # The submodule operations should be done relative to the current submodule's + # supermodule. + if self.topmost_supermodule_path_prefix: + os.chdir(self.topmost_supermodule_path_prefix) + if os.path.isdir(self.path): self.reset() @@ -203,9 +232,9 @@ class Submodule: print '-- skipping ' + self.path + ' for this operating system. --' def listFiles(self): - if self.matchesOS() and os.path.isdir(self.path): + if self.matchesOS() and os.path.isdir(self.pathRelativeToTopMostSupermodule()): currentDir = os.getcwd() - os.chdir(self.path) + os.chdir(self.pathRelativeToTopMostSupermodule()) files = subprocessCheckOutput(['git', 'ls-files']).splitlines() os.chdir(currentDir) return files @@ -213,6 +242,54 @@ class Submodule: print '-- skipping ' + self.path + ' for this operating system. --' return [] + def parseGitModulesFileContents(self, gitmodules_lines): + submodules = [] + currentSubmodule = None + for line in gitmodules_lines: + if line.find('[submodule') == 0: + if currentSubmodule: + submodules.append(currentSubmodule) + currentSubmodule = Submodule() + tokens = line.split('=') + if len(tokens) >= 2: + key = tokens[0].strip() + value = tokens[1].strip() + if key == 'path': + currentSubmodule.path = value + elif key == 'url': + currentSubmodule.url = value + elif key == 'os': + currentSubmodule.os = value.split(',') + if currentSubmodule: + submodules.append(currentSubmodule) + return submodules + + # Return a flattened list of submodules starting from module, and recursively collecting child + # submodules. + def readSubmodulesFromGitModules(self, module, gitmodules_file_name, top_level_path): + flattened_submodules = [] + oldCwd = os.getcwd() + os.chdir(module.path) + + if os.path.isfile(gitmodules_file_name): + gitmodules_file = open(gitmodules_file_name) + gitmodules_lines = gitmodules_file.readlines() + gitmodules_file.close() + submodules = self.parseGitModulesFileContents(gitmodules_lines) + + # When inside a 2nd level submodule or deeper, store the path relative to the topmost + # module. + for submodule in submodules: + submodule.topmost_supermodule_path_prefix = computeRelativePathPrefixToTopMostSupermodule(submodule.path, top_level_path) + + flattened_submodules.extend(submodules) + + # Recurse into deeper submodules. + for submodule in submodules: + flattened_submodules.extend(self.readSubmodulesFromGitModules(submodule, gitmodules_file_name, top_level_path)) + + os.chdir(oldCwd) + return flattened_submodules def readSubmodules(self): submodules = [] @@ -220,33 +297,10 @@ class Submodule: submodules = resolver.readSubmodules() print 'DEPS file provides the following submodules:' for submodule in submodules: - print '{:<80}'.format(submodule.path) + '{:<120}'.format(submodule.url) + submodule.ref + print '{:<80}'.format(submodule.pathRelativeToTopMostSupermodule()) + '{:<120}'.format(submodule.url) + submodule.ref else: # Try .gitmodules since no ref has been specified - if not os.path.isfile('.gitmodules'): - return [] - gitmodules_file = open('.gitmodules') - gitmodules_lines = gitmodules_file.readlines() - gitmodules_file.close() - - submodules = [] - currentSubmodule = None - for line in gitmodules_lines: - if line.find('[submodule') == 0: - if currentSubmodule: - submodules.append(currentSubmodule) - currentSubmodule = Submodule() - tokens = line.split('=') - if len(tokens) >= 2: - key = tokens[0].strip() - value = tokens[1].strip() - if key == 'path': - currentSubmodule.path = value - elif key == 'url': - currentSubmodule.url = value - elif key == 'os': - currentSubmodule.os = value.split(',') - if currentSubmodule: - submodules.append(currentSubmodule) + gitmodules_file_name = '.gitmodules' + submodules = self.readSubmodulesFromGitModules(self, gitmodules_file_name, self.path) return submodules def initSubmodules(self): diff --git a/tools/scripts/take_snapshot.py b/tools/scripts/take_snapshot.py index f5a1ed9d9..25b3dc15e 100755 --- a/tools/scripts/take_snapshot.py +++ b/tools/scripts/take_snapshot.py @@ -78,6 +78,7 @@ def isInChromiumBlacklist(file_path): or file_path.startswith('base/android/java') or file_path.startswith('breakpad') or file_path.startswith('build/android/') + or file_path.startswith('buildtools/clang_format/script') or (file_path.startswith('chrome/') and not file_path.startswith('chrome/VERSION') and not file_path.startswith('chrome/browser/chrome_notification_types.h') and @@ -204,6 +205,7 @@ def isInChromiumBlacklist(file_path): or file_path.startswith('third_party/trace-viewer') or file_path.startswith('third_party/undoview') or file_path.startswith('third_party/webgl') + or file_path.startswith('tools/memory_inspector') or (file_path.startswith('tools') and not file_path.startswith('tools/clang') and not file_path.startswith('tools/compile_test') and @@ -215,7 +217,10 @@ def isInChromiumBlacklist(file_path): not file_path.startswith('tools/json_comment_eater') and not file_path.startswith('tools/json_schema_compiler') and not file_path.startswith('tools/idl_parser') and - not file_path.startswith('tools/protoc_wrapper')) + not file_path.startswith('tools/memory') and + not file_path.startswith('tools/msan') and + not file_path.startswith('tools/protoc_wrapper') and + not file_path.startswith('tools/ubsan')) or file_path.startswith('ui/android/java') or file_path.startswith('ui/app_list') or file_path.startswith('ui/base/ime/chromeos') @@ -274,7 +279,7 @@ def listFilesInCurrentRepository(): for submodule in submodules: submodule_files = submodule.listFiles() for submodule_file in submodule_files: - files.append(os.path.join(submodule.path, submodule_file)) + files.append(os.path.join(submodule.pathRelativeToTopMostSupermodule(), submodule_file)) return files def exportNinja(): diff --git a/tools/scripts/version_resolver.py b/tools/scripts/version_resolver.py index 634fec23e..6029bbdc9 100644 --- a/tools/scripts/version_resolver.py +++ b/tools/scripts/version_resolver.py @@ -89,6 +89,18 @@ def readSubmodules(): for sub in git_submodules: submodule_dict[sub.path] = sub + # Add buildtools submodules + buildtools_deps_file_path = "buildtools/DEPS" + if (os.path.isfile(buildtools_deps_file_path)): + with open(buildtools_deps_file_path, 'r') as buildtools_deps_file: + buildtools_deps = buildtools_deps_file.read() + if buildtools_deps: + buildtools_parser = GitSubmodule.DEPSParser() + buildtools_parser.topmost_supermodule_path_prefix = './buildtools/' + buildtools_submodules = buildtools_parser.parse(buildtools_deps) + for sub in buildtools_submodules: + submodule_dict[sub.path] = sub + # Remove unwanted upstream submodules for path in submodule_blacklist: if path in submodule_dict: |