diff options
110 files changed, 2674 insertions, 307 deletions
diff --git a/.qmake.conf b/.qmake.conf index fe1cde075..ccd743b86 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -2,4 +2,4 @@ QMAKEPATH += $$PWD/tools/qmake load(qt_build_config) CONFIG += qt_example_installs -MODULE_VERSION = 5.6.0 +MODULE_VERSION = 5.7.0 diff --git a/examples/webenginewidgets/demobrowser/demobrowser.pro b/examples/webenginewidgets/demobrowser/demobrowser.pro index 113eeb40e..e295cd9dd 100644 --- a/examples/webenginewidgets/demobrowser/demobrowser.pro +++ b/examples/webenginewidgets/demobrowser/demobrowser.pro @@ -16,6 +16,7 @@ FORMS += \ history.ui \ passworddialog.ui \ proxy.ui \ + savepagedialog.ui \ settings.ui HEADERS += \ @@ -31,6 +32,7 @@ HEADERS += \ fullscreennotification.h \ history.h \ modelmenu.h \ + savepagedialog.h \ searchlineedit.h \ settings.h \ squeezelabel.h \ @@ -53,6 +55,7 @@ SOURCES += \ fullscreennotification.cpp \ history.cpp \ modelmenu.cpp \ + savepagedialog.cpp \ searchlineedit.cpp \ settings.cpp \ squeezelabel.cpp \ diff --git a/examples/webenginewidgets/demobrowser/savepagedialog.cpp b/examples/webenginewidgets/demobrowser/savepagedialog.cpp new file mode 100644 index 000000000..e3a653ea1 --- /dev/null +++ b/examples/webenginewidgets/demobrowser/savepagedialog.cpp @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +#include "savepagedialog.h" +#include "ui_savepagedialog.h" + +#include <QtCore/QDir> +#include <QtWidgets/QFileDialog> + +const QWebEngineDownloadItem::SavePageFormat SavePageDialog::m_indexToFormatTable[] = { + QWebEngineDownloadItem::SingleHtmlSaveFormat, + QWebEngineDownloadItem::CompleteHtmlSaveFormat, + QWebEngineDownloadItem::MimeHtmlSaveFormat +}; + +SavePageDialog::SavePageDialog(QWidget *parent, QWebEngineDownloadItem::SavePageFormat format, + const QString &filePath) + : QDialog(parent) + , ui(new Ui::SavePageDialog) +{ + ui->setupUi(this); + ui->formatComboBox->setCurrentIndex(formatToIndex(format)); + setFilePath(filePath); +} + +SavePageDialog::~SavePageDialog() +{ + delete ui; +} + +QWebEngineDownloadItem::SavePageFormat SavePageDialog::pageFormat() const +{ + return indexToFormat(ui->formatComboBox->currentIndex()); +} + +QString SavePageDialog::filePath() const +{ + return QDir::fromNativeSeparators(ui->filePathLineEdit->text()); +} + +void SavePageDialog::on_chooseFilePathButton_clicked() +{ + QFileInfo fi(filePath()); + QFileDialog dlg(this, tr("Save Page As"), fi.absolutePath()); + dlg.setAcceptMode(QFileDialog::AcceptSave); + dlg.setDefaultSuffix(suffixOfFormat(pageFormat())); + dlg.selectFile(fi.absoluteFilePath()); + if (dlg.exec() != QDialog::Accepted) + return; + setFilePath(dlg.selectedFiles().first()); + ensureFileSuffix(pageFormat()); +} + +void SavePageDialog::on_formatComboBox_currentIndexChanged(int idx) +{ + ensureFileSuffix(indexToFormat(idx)); +} + +int SavePageDialog::formatToIndex(QWebEngineDownloadItem::SavePageFormat format) +{ + for (auto i : m_indexToFormatTable) { + if (m_indexToFormatTable[i] == format) + return i; + } + Q_UNREACHABLE(); +} + +QWebEngineDownloadItem::SavePageFormat SavePageDialog::indexToFormat(int idx) +{ + Q_ASSERT(idx >= 0 && size_t(idx) < (sizeof(m_indexToFormatTable) + / sizeof(QWebEngineDownloadItem::SavePageFormat))); + return m_indexToFormatTable[idx]; +} + +QString SavePageDialog::suffixOfFormat(QWebEngineDownloadItem::SavePageFormat format) +{ + if (format == QWebEngineDownloadItem::MimeHtmlSaveFormat) + return QStringLiteral(".mhtml"); + return QStringLiteral(".html"); +} + +void SavePageDialog::setFilePath(const QString &filePath) +{ + ui->filePathLineEdit->setText(QDir::toNativeSeparators(filePath)); +} + +void SavePageDialog::ensureFileSuffix(QWebEngineDownloadItem::SavePageFormat format) +{ + QFileInfo fi(filePath()); + setFilePath(fi.absolutePath() + QLatin1Char('/') + fi.completeBaseName() + + suffixOfFormat(format)); +} diff --git a/examples/webenginewidgets/demobrowser/savepagedialog.h b/examples/webenginewidgets/demobrowser/savepagedialog.h new file mode 100644 index 000000000..50c79ee3a --- /dev/null +++ b/examples/webenginewidgets/demobrowser/savepagedialog.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +#ifndef SAVEPAGEDIALOG_H +#define SAVEPAGEDIALOG_H + +#include <QtWidgets/QDialog> +#include <QtWebEngineWidgets/QWebEngineDownloadItem> + +QT_BEGIN_NAMESPACE +namespace Ui { +class SavePageDialog; +} +QT_END_NAMESPACE + +class SavePageDialog : public QDialog +{ + Q_OBJECT + +public: + explicit SavePageDialog(QWidget *parent, QWebEngineDownloadItem::SavePageFormat format, + const QString &filePath); + ~SavePageDialog(); + + QWebEngineDownloadItem::SavePageFormat pageFormat() const; + QString filePath() const; + +private slots: + void on_chooseFilePathButton_clicked(); + void on_formatComboBox_currentIndexChanged(int idx); + +private: + static int formatToIndex(QWebEngineDownloadItem::SavePageFormat format); + static QWebEngineDownloadItem::SavePageFormat indexToFormat(int idx); + static QString suffixOfFormat(QWebEngineDownloadItem::SavePageFormat format); + void setFilePath(const QString &filePath); + void ensureFileSuffix(QWebEngineDownloadItem::SavePageFormat format); + + static const QWebEngineDownloadItem::SavePageFormat m_indexToFormatTable[]; + Ui::SavePageDialog *ui; +}; + +#endif // SAVEPAGEDIALOG_H diff --git a/examples/webenginewidgets/demobrowser/savepagedialog.ui b/examples/webenginewidgets/demobrowser/savepagedialog.ui new file mode 100644 index 000000000..9aa7cbe55 --- /dev/null +++ b/examples/webenginewidgets/demobrowser/savepagedialog.ui @@ -0,0 +1,139 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>SavePageDialog</class> + <widget class="QDialog" name="SavePageDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>121</height> + </rect> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>&Format:</string> + </property> + <property name="buddy"> + <cstring>formatComboBox</cstring> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="formatComboBox"> + <item> + <property name="text"> + <string>Single HTML</string> + </property> + </item> + <item> + <property name="text"> + <string>Complete HTML</string> + </property> + </item> + <item> + <property name="text"> + <string>MIME HTML</string> + </property> + </item> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>&Save to:</string> + </property> + <property name="buddy"> + <cstring>filePathLineEdit</cstring> + </property> + </widget> + </item> + <item row="1" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLineEdit" name="filePathLineEdit"/> + </item> + <item> + <widget class="QToolButton" name="chooseFilePathButton"> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>12</height> + </size> + </property> + </spacer> + </item> + <item> + <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> + </layout> + </widget> + <tabstops> + <tabstop>formatComboBox</tabstop> + <tabstop>filePathLineEdit</tabstop> + <tabstop>chooseFilePathButton</tabstop> + </tabstops> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>SavePageDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>227</x> + <y>104</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>120</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>SavePageDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>295</x> + <y>110</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>120</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/examples/webenginewidgets/demobrowser/tabwidget.cpp b/examples/webenginewidgets/demobrowser/tabwidget.cpp index a14b22ffd..b744fad90 100644 --- a/examples/webenginewidgets/demobrowser/tabwidget.cpp +++ b/examples/webenginewidgets/demobrowser/tabwidget.cpp @@ -46,6 +46,7 @@ #include "downloadmanager.h" #include "fullscreennotification.h" #include "history.h" +#include "savepagedialog.h" #include "urllineedit.h" #include "webview.h" @@ -126,6 +127,15 @@ void TabBar::contextMenuRequested(const QPoint &position) action = menu.addAction(tr("Reload Tab"), this, SLOT(reloadTab()), QKeySequence::Refresh); action->setData(index); + + // Audio mute / unmute. + action = menu.addAction(tr("Mute tab"), + this, SLOT(muteTab())); + action->setData(index); + + action = menu.addAction(tr("Unmute tab"), + this, SLOT(unmuteTab())); + action->setData(index); } else { menu.addSeparator(); } @@ -219,6 +229,22 @@ void TabBar::reloadTab() } } +void TabBar::muteTab() +{ + if (QAction *action = qobject_cast<QAction*>(sender())) { + int index = action->data().toInt(); + emit muteTab(index, true); + } +} + +void TabBar::unmuteTab() +{ + if (QAction *action = qobject_cast<QAction*>(sender())) { + int index = action->data().toInt(); + emit muteTab(index, false); + } +} + TabWidget::TabWidget(QWidget *parent) : QTabWidget(parent) , m_recentlyClosedTabsAction(0) @@ -244,6 +270,7 @@ TabWidget::TabWidget(QWidget *parent) connect(m_tabBar, SIGNAL(reloadAllTabs()), this, SLOT(reloadAllTabs())); connect(m_tabBar, SIGNAL(tabMoved(int,int)), this, SLOT(moveTab(int,int))); connect(m_tabBar, SIGNAL(tabBarDoubleClicked(int)), this, SLOT(handleTabBarDoubleClicked(int))); + connect(m_tabBar, SIGNAL(muteTab(int,bool)), this, SLOT(setAudioMutedForTab(int,bool))); setTabBar(m_tabBar); setDocumentMode(true); @@ -309,6 +336,18 @@ void TabWidget::moveTab(int fromIndex, int toIndex) m_lineEdits->insertWidget(toIndex, lineEdit); } +void TabWidget::setAudioMutedForTab(int index, bool mute) +{ + if (index < 0) + index = currentIndex(); + if (index < 0 || index >= count()) + return; + + QWidget *widget = this->widget(index); + if (WebView *tab = qobject_cast<WebView*>(widget)) + tab->page()->setAudioMuted(mute); +} + void TabWidget::addWebAction(QAction *action, QWebEnginePage::WebAction webAction) { if (!action) @@ -553,6 +592,10 @@ WebView *TabWidget::newTab(bool makeCurrent) this, SLOT(webViewIconChanged())); connect(webView, SIGNAL(titleChanged(QString)), this, SLOT(webViewTitleChanged(QString))); + connect(webView->page(), SIGNAL(audioMutedChanged(bool)), + this, SLOT(webPageMutedOrAudibleChanged())); + connect(webView->page(), SIGNAL(wasRecentlyAudibleChanged(bool)), + this, SLOT(webPageMutedOrAudibleChanged())); connect(webView, SIGNAL(urlChanged(QUrl)), this, SLOT(webViewUrlChanged(QUrl))); @@ -706,6 +749,23 @@ void TabWidget::webViewTitleChanged(const QString &title) BrowserApplication::historyManager()->updateHistoryItem(webView->url(), title); } +void TabWidget::webPageMutedOrAudibleChanged() { + QWebEnginePage* webPage = qobject_cast<QWebEnginePage*>(sender()); + WebView *webView = qobject_cast<WebView*>(webPage->view()); + + int index = webViewIndex(webView); + if (-1 != index) { + QString title = webView->title(); + + bool muted = webPage->isAudioMuted(); + bool audible = webPage->wasRecentlyAudible(); + if (muted) title += tr(" (muted)"); + else if (audible) title += tr(" (audible)"); + + setTabText(index, title); + } +} + void TabWidget::webViewUrlChanged(const QUrl &url) { WebView *webView = qobject_cast<WebView*>(sender()); @@ -850,6 +910,14 @@ bool TabWidget::restoreState(const QByteArray &state) void TabWidget::downloadRequested(QWebEngineDownloadItem *download) { + if (download->savePageFormat() != QWebEngineDownloadItem::UnknownSaveFormat) { + SavePageDialog dlg(this, download->savePageFormat(), download->path()); + if (dlg.exec() != SavePageDialog::Accepted) + return; + download->setSavePageFormat(dlg.pageFormat()); + download->setPath(dlg.filePath()); + } + BrowserApplication::downloadManager()->download(download); download->accept(); } diff --git a/examples/webenginewidgets/demobrowser/tabwidget.h b/examples/webenginewidgets/demobrowser/tabwidget.h index 872e1c11b..c6eef58f9 100644 --- a/examples/webenginewidgets/demobrowser/tabwidget.h +++ b/examples/webenginewidgets/demobrowser/tabwidget.h @@ -65,6 +65,7 @@ signals: void closeTab(int index); void closeOtherTabs(int index); void reloadTab(int index); + void muteTab(int index, bool mute); void reloadAllTabs(); void tabMoveRequested(int fromIndex, int toIndex); @@ -81,6 +82,8 @@ private slots: void closeTab(); void closeOtherTabs(); void reloadTab(); + void muteTab(); + void unmuteTab(); void contextMenuRequested(const QPoint &position); private: @@ -207,6 +210,7 @@ public slots: void reloadAllTabs(); void nextTab(); void previousTab(); + void setAudioMutedForTab(int index, bool mute); private slots: void currentChanged(int index); @@ -222,6 +226,7 @@ private slots: void moveTab(int fromIndex, int toIndex); void fullScreenRequested(QWebEngineFullScreenRequest request); void handleTabBarDoubleClicked(int index); + void webPageMutedOrAudibleChanged(); private: void setupPage(QWebEnginePage* page); diff --git a/src/3rdparty b/src/3rdparty -Subproject 4cb3a5a4f03774ae47d69a84a3423d14e59a2d2 +Subproject e921076fcf1736db4aeb76877c6f608f42f4acc diff --git a/src/core/browser_accessibility_manager_qt.cpp b/src/core/browser_accessibility_manager_qt.cpp index 7c59db110..4d6686d52 100644 --- a/src/core/browser_accessibility_manager_qt.cpp +++ b/src/core/browser_accessibility_manager_qt.cpp @@ -44,12 +44,12 @@ using namespace blink; namespace content { BrowserAccessibilityManager* BrowserAccessibilityManager::Create( - const ui::AXTreeUpdate& initial_tree, + const SimpleAXTreeUpdate& initialTree, BrowserAccessibilityDelegate* delegate, BrowserAccessibilityFactory* factory) { #ifndef QT_NO_ACCESSIBILITY - return new BrowserAccessibilityManagerQt(0, initial_tree, delegate); + return new BrowserAccessibilityManagerQt(0, initialTree, delegate); #else return 0; #endif // QT_NO_ACCESSIBILITY @@ -67,7 +67,7 @@ BrowserAccessibility *BrowserAccessibilityFactoryQt::Create() #ifndef QT_NO_ACCESSIBILITY BrowserAccessibilityManagerQt::BrowserAccessibilityManagerQt( QObject* parentObject, - const ui::AXTreeUpdate& initialTree, + const SimpleAXTreeUpdate& initialTree, BrowserAccessibilityDelegate* delegate, BrowserAccessibilityFactory* factory) : BrowserAccessibilityManager(delegate, factory) diff --git a/src/core/browser_accessibility_manager_qt.h b/src/core/browser_accessibility_manager_qt.h index 08dcdf4c6..3b1baf21d 100644 --- a/src/core/browser_accessibility_manager_qt.h +++ b/src/core/browser_accessibility_manager_qt.h @@ -58,7 +58,7 @@ class BrowserAccessibilityManagerQt : public BrowserAccessibilityManager public: BrowserAccessibilityManagerQt( QObject* parentObject, - const ui::AXTreeUpdate& initialTree, + const SimpleAXTreeUpdate& initialTree, BrowserAccessibilityDelegate* delegate, BrowserAccessibilityFactory* factory = new BrowserAccessibilityFactoryQt()); diff --git a/src/core/browser_context_adapter.cpp b/src/core/browser_context_adapter.cpp index 0bbb13857..a8f704995 100644 --- a/src/core/browser_context_adapter.cpp +++ b/src/core/browser_context_adapter.cpp @@ -422,4 +422,10 @@ void BrowserContextAdapter::setHttpAcceptLanguage(const QString &httpAcceptLangu m_httpAcceptLanguage = httpAcceptLanguage; } +void BrowserContextAdapter::clearHttpCache() +{ + if (m_browserContext->url_request_getter_.get()) + m_browserContext->url_request_getter_->clearHttpCache(); +} + } // namespace QtWebEngineCore diff --git a/src/core/browser_context_adapter.h b/src/core/browser_context_adapter.h index 97a4dca4a..ee913b8cb 100644 --- a/src/core/browser_context_adapter.h +++ b/src/core/browser_context_adapter.h @@ -157,6 +157,8 @@ public: QString httpAcceptLanguage() const; void setHttpAcceptLanguage(const QString &httpAcceptLanguage); + void clearHttpCache(); + private: QString m_name; bool m_offTheRecord; diff --git a/src/core/browser_context_adapter_client.h b/src/core/browser_context_adapter_client.h index efa889e75..5c0674a0a 100644 --- a/src/core/browser_context_adapter_client.h +++ b/src/core/browser_context_adapter_client.h @@ -58,6 +58,14 @@ public: DownloadInterrupted }; + // Keep in sync with content::SavePageType + enum SavePageFormat { + UnknownSavePageFormat = -1, + SingleHtmlSaveFormat, + CompleteHtmlSaveFormat, + MimeHtmlSaveFormat + }; + struct DownloadItemInfo { const quint32 id; const QUrl url; @@ -67,6 +75,7 @@ public: const QString mimeType; QString path; + int savePageFormat; bool accepted; }; diff --git a/src/core/certificate_error_controller.cpp b/src/core/certificate_error_controller.cpp index 3a95458ea..340881fa8 100644 --- a/src/core/certificate_error_controller.cpp +++ b/src/core/certificate_error_controller.cpp @@ -41,6 +41,7 @@ #include <net/ssl/ssl_info.h> #include <ui/base/l10n/l10n_util.h> #include "chrome/grit/generated_resources.h" +#include "components/strings/grit/components_strings.h" #include "type_conversion.h" QT_BEGIN_NAMESPACE @@ -125,7 +126,7 @@ QString CertificateErrorController::errorString() const // formatted text. switch (d->certError) { case SslPinnedKeyNotInCertificateChain: - return getQStringForMessageId(IDS_ERRORPAGES_SUMMARY_PINNING_FAILURE); + return getQStringForMessageId(IDS_CERT_ERROR_SUMMARY_PINNING_FAILURE_DETAILS); case CertificateCommonNameInvalid: return getQStringForMessageId(IDS_CERT_ERROR_COMMON_NAME_INVALID_DESCRIPTION); case CertificateDateInvalid: diff --git a/src/core/chrome_qt.gyp b/src/core/chrome_qt.gyp index de49d8826..6c8e0d4d6 100644 --- a/src/core/chrome_qt.gyp +++ b/src/core/chrome_qt.gyp @@ -8,12 +8,16 @@ 'type': 'static_library', 'dependencies': [ 'chrome_resources', + '<(chromium_src_dir)/components/components_strings.gyp:components_strings', ], 'include_dirs': [ './', '<(chromium_src_dir)', '<(chromium_src_dir)/skia/config', - '<(SHARED_INTERMEDIATE_DIR)/chrome', # Needed to include grit-generated files in localized_error.cc + '<(chromium_src_dir)/third_party/skia/include/core', + # Needed to include grit-generated files in localized_error.cc: + '<(SHARED_INTERMEDIATE_DIR)/chrome', + '<(SHARED_INTERMEDIATE_DIR)/components/strings', ], 'sources': [ '<(DEPTH)/chrome/browser/media/desktop_streams_registry.cc', diff --git a/src/core/chromium_gpu_helper.cpp b/src/core/chromium_gpu_helper.cpp index 9dfc498ad..6bb01ade5 100644 --- a/src/core/chromium_gpu_helper.cpp +++ b/src/core/chromium_gpu_helper.cpp @@ -87,7 +87,7 @@ gpu::SyncPointManager *sync_point_manager() void AddSyncPointCallbackOnGpuThread(base::MessageLoop *gpuMessageLoop, gpu::SyncPointManager *syncPointManager, uint32 sync_point, const base::Closure& callback) { // We need to set our callback from the GPU thread, where the SyncPointManager lives. - gpuMessageLoop->PostTask(FROM_HERE, base::Bind(&addSyncPointCallbackDelegate, make_scoped_refptr(syncPointManager), sync_point, callback)); + gpuMessageLoop->PostTask(FROM_HERE, base::Bind(&addSyncPointCallbackDelegate, syncPointManager, sync_point, callback)); } gpu::gles2::MailboxManager *mailbox_manager() diff --git a/src/core/chromium_overrides.cpp b/src/core/chromium_overrides.cpp index b9ce722dd..98807e387 100644 --- a/src/core/chromium_overrides.cpp +++ b/src/core/chromium_overrides.cpp @@ -157,3 +157,16 @@ OSExchangeData::Provider* OSExchangeData::CreateProvider() } // namespace ui #endif // defined(USE_AURA) && !defined(USE_OZONE) + +#if defined(USE_OPENSSL_CERTS) +namespace net { +class SSLPrivateKey { }; +class X509Certificate; + +scoped_ptr<SSLPrivateKey> FetchClientCertPrivateKey(X509Certificate* certificate, scoped_refptr<base::SequencedTaskRunner> task_runner) +{ + return scoped_ptr<SSLPrivateKey>(); +} + +} // namespace net +#endif diff --git a/src/core/color_chooser_controller.cpp b/src/core/color_chooser_controller.cpp new file mode 100644 index 000000000..da856d90e --- /dev/null +++ b/src/core/color_chooser_controller.cpp @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2015 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "content/browser/web_contents/web_contents_impl.h" + +#include "color_chooser_controller.h" +#include "color_chooser_controller_p.h" +#include "type_conversion.h" + +namespace QtWebEngineCore { + +ColorChooserControllerPrivate::ColorChooserControllerPrivate(content::WebContents *content, const QColor &color) + : m_content(content) + , m_initialColor(color) +{ +} + +ColorChooserController::~ColorChooserController() +{ +} + +ColorChooserController::ColorChooserController(ColorChooserControllerPrivate *dd) +{ + Q_ASSERT(dd); + d.reset(dd); +} + +QColor ColorChooserController::initialColor() const +{ + return d->m_initialColor; +} + +void ColorChooserController::didEndColorDialog() +{ + d->m_content->DidEndColorChooser(); +} + +void ColorChooserController::didChooseColorInColorDialog(const QColor &color) +{ + d->m_content->DidChooseColorInColorChooser(toSk(color)); +} + +void ColorChooserController::accept(const QColor &color) +{ + didChooseColorInColorDialog(color); + didEndColorDialog(); +} + +void ColorChooserController::accept(const QVariant &color) +{ + QColor selectedColor; + if (color.canConvert<QColor>()) { + selectedColor = color.value<QColor>(); + didChooseColorInColorDialog(selectedColor); + } + + didEndColorDialog(); +} + +void ColorChooserController::reject() +{ + didEndColorDialog(); +} + + +} // namespace diff --git a/src/core/color_chooser_controller.h b/src/core/color_chooser_controller.h new file mode 100644 index 000000000..609366967 --- /dev/null +++ b/src/core/color_chooser_controller.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2015 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef COLOR_CHOOSER_CONTROLLER_H +#define COLOR_CHOOSER_CONTROLLER_H + +#include "qtwebenginecoreglobal.h" + +#include <QObject> + +namespace QtWebEngineCore { + +class ColorChooserControllerPrivate; + +class QWEBENGINE_EXPORT ColorChooserController : public QObject { + Q_OBJECT +public: + ~ColorChooserController(); + + QColor initialColor() const; + + void didEndColorDialog(); + void didChooseColorInColorDialog(const QColor &); + +public Q_SLOTS: + void accept(const QColor &); + void accept(const QVariant &); + void reject(); + +private: + ColorChooserController(ColorChooserControllerPrivate *); + QScopedPointer<ColorChooserControllerPrivate> d; + + friend class ColorChooserQt; +}; + +} // namespace + +#endif // COLOR_CHOOSER_CONTROLLER_H diff --git a/src/core/color_chooser_controller_p.h b/src/core/color_chooser_controller_p.h new file mode 100644 index 000000000..a78e735a6 --- /dev/null +++ b/src/core/color_chooser_controller_p.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2015 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef COLOR_CHOOSER_CONTROLLER_P_H +#define COLOR_CHOOSER_CONTROLLER_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 <QColor> + +namespace content { + class WebContents; +} + +namespace QtWebEngineCore { + +class ColorChooserControllerPrivate { + +public: + ColorChooserControllerPrivate(content::WebContents *, const QColor &); + content::WebContents *m_content; + QColor m_initialColor; +}; + +} // namespace + +#endif // COLOR_CHOOSER_CONTROLLER_P_H + diff --git a/src/core/color_chooser_qt.cpp b/src/core/color_chooser_qt.cpp new file mode 100644 index 000000000..a8f03be10 --- /dev/null +++ b/src/core/color_chooser_qt.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2015 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "color_chooser_qt.h" +#include "color_chooser_controller.h" +#include "color_chooser_controller_p.h" + +namespace content { + class WebContents; +} + +namespace QtWebEngineCore { + +ColorChooserQt::ColorChooserQt(content::WebContents *content, const QColor &color) +{ + m_controller.reset(new ColorChooserController(new ColorChooserControllerPrivate(content, color))); +} + +QSharedPointer<ColorChooserController> ColorChooserQt::controller() +{ + return m_controller; +} + +} // namespace diff --git a/src/core/color_chooser_qt.h b/src/core/color_chooser_qt.h new file mode 100644 index 000000000..b1e76b14c --- /dev/null +++ b/src/core/color_chooser_qt.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2015 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef COLOR_CHOOSER_QT_H +#define COLOR_CHOOSER_QT_H + +#include "content/public/browser/color_chooser.h" +#include "type_conversion.h" + +#include <QColor> +#include <QSharedPointer> + +namespace content { + class WebContents; +} + +namespace QtWebEngineCore { + +class ColorChooserController; + +class ColorChooserQt : public content::ColorChooser +{ +public: + ColorChooserQt(content::WebContents *, const QColor &); + + virtual void SetSelectedColor(SkColor color) Q_DECL_OVERRIDE { } + virtual void End() Q_DECL_OVERRIDE {} + + QSharedPointer<ColorChooserController> controller(); + +private: + QSharedPointer<ColorChooserController> m_controller; +}; + + +} // namespace + +#endif // COLOR_CHOOSER_QT_H diff --git a/src/core/common/qt_messages.h b/src/core/common/qt_messages.h index ae36a0d7f..02f8716d6 100644 --- a/src/core/common/qt_messages.h +++ b/src/core/common/qt_messages.h @@ -34,6 +34,7 @@ IPC_MESSAGE_ROUTED1(RenderViewObserverQt_FetchDocumentInnerText, IPC_MESSAGE_ROUTED1(RenderViewObserverQt_SetBackgroundColor, uint32 /* color */) +IPC_MESSAGE_ROUTED0(WebChannelIPCTransport_Install) IPC_MESSAGE_ROUTED1(WebChannelIPCTransport_Message, std::vector<char> /*binaryJSON*/) // User scripts messages diff --git a/src/core/config/linux.pri b/src/core/config/linux.pri index 9868d6848..c3398757e 100644 --- a/src/core/config/linux.pri +++ b/src/core/config/linux.pri @@ -38,7 +38,6 @@ use?(system_flac): GYP_CONFIG += use_system_flac=1 use?(system_jsoncpp): GYP_CONFIG += use_system_jsoncpp=1 use?(system_opus): GYP_CONFIG += use_system_opus=1 use?(system_snappy): GYP_CONFIG += use_system_snappy=1 -use?(system_speex): GYP_CONFIG += use_system_speex=1 use?(system_vpx): GYP_CONFIG += use_system_libvpx=1 use?(system_icu): GYP_CONFIG += use_system_icu=1 use?(system_ffmpeg): GYP_CONFIG += use_system_ffmpeg=1 diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index 078874da1..61e0f3399 100644 --- a/src/core/content_browser_client_qt.cpp +++ b/src/core/content_browser_client_qt.cpp @@ -280,7 +280,6 @@ public: // We don't care about the rest, this context shouldn't be used except for its handle. virtual bool Initialize(gfx::GLSurface *, gfx::GpuPreference) Q_DECL_OVERRIDE { Q_UNREACHABLE(); return false; } - virtual void Destroy() Q_DECL_OVERRIDE { Q_UNREACHABLE(); } virtual bool MakeCurrent(gfx::GLSurface *) Q_DECL_OVERRIDE { Q_UNREACHABLE(); return false; } virtual void ReleaseCurrent(gfx::GLSurface *) Q_DECL_OVERRIDE { Q_UNREACHABLE(); } virtual bool IsCurrent(gfx::GLSurface *) Q_DECL_OVERRIDE { Q_UNREACHABLE(); return false; } diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp index ccc97517e..8d7ea397b 100644 --- a/src/core/content_client_qt.cpp +++ b/src/core/content_client_qt.cpp @@ -74,8 +74,7 @@ content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path, cons plugin.path = path; plugin.permissions = kPepperFlashPermissions; - std::vector<std::string> flash_version_numbers; - base::SplitString(version, '.', &flash_version_numbers); + std::vector<std::string> flash_version_numbers = base::SplitString(version, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); if (flash_version_numbers.size() < 1) flash_version_numbers.push_back("11"); else if (flash_version_numbers[0].empty()) @@ -89,7 +88,7 @@ content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path, cons // E.g., "Shockwave Flash 10.2 r154": plugin.description = plugin.name + " " + flash_version_numbers[0] + "." + flash_version_numbers[1] + " r" + flash_version_numbers[2]; - plugin.version = JoinString(flash_version_numbers, '.'); + plugin.version = base::JoinString(flash_version_numbers, "."); content::WebPluginMimeType swf_mime_type(content::kFlashPluginSwfMimeType, content::kFlashPluginSwfExtension, content::kFlashPluginSwfDescription); diff --git a/src/core/core_gyp_generator.pro b/src/core/core_gyp_generator.pro index 0685abd7e..7145d8e04 100644 --- a/src/core/core_gyp_generator.pro +++ b/src/core/core_gyp_generator.pro @@ -39,6 +39,8 @@ SOURCES = \ chromium_gpu_helper.cpp \ chromium_overrides.cpp \ clipboard_qt.cpp \ + color_chooser_qt.cpp \ + color_chooser_controller.cpp \ common/qt_messages.cpp \ common/user_script_data.cpp \ content_client_qt.cpp \ @@ -79,6 +81,7 @@ SOURCES = \ resource_dispatcher_host_delegate_qt.cpp \ stream_video_node.cpp \ surface_factory_qt.cpp \ + type_conversion.cpp \ url_request_context_getter_qt.cpp \ url_request_custom_job.cpp \ url_request_custom_job_delegate.cpp \ @@ -110,6 +113,9 @@ HEADERS = \ certificate_error_controller.h \ chromium_overrides.h \ clipboard_qt.h \ + color_chooser_qt.h \ + color_chooser_controller_p.h \ + color_chooser_controller.h \ common/qt_messages.h \ common/user_script_data.h \ content_client_qt.h \ diff --git a/src/core/delegated_frame_node.cpp b/src/core/delegated_frame_node.cpp index 07b3131ce..a2836d5e6 100644 --- a/src/core/delegated_frame_node.cpp +++ b/src/core/delegated_frame_node.cpp @@ -54,7 +54,6 @@ #include "base/message_loop/message_loop.h" #include "base/bind.h" #include "cc/output/delegated_frame_data.h" -#include "cc/quads/checkerboard_draw_quad.h" #include "cc/quads/debug_border_draw_quad.h" #include "cc/quads/draw_quad.h" #include "cc/quads/io_surface_draw_quad.h" @@ -551,15 +550,7 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, } switch (quad->material) { - case cc::DrawQuad::CHECKERBOARD: { - const cc::CheckerboardDrawQuad *cbquad = cc::CheckerboardDrawQuad::MaterialCast(quad); - QSGSimpleRectNode *rectangleNode = new QSGSimpleRectNode; - - rectangleNode->setRect(toQt(quad->rect)); - rectangleNode->setColor(toQt(cbquad->color)); - currentLayerChain->appendChildNode(rectangleNode); - break; - } case cc::DrawQuad::RENDER_PASS: { + case cc::DrawQuad::RENDER_PASS: { const cc::RenderPassDrawQuad *renderPassQuad = cc::RenderPassDrawQuad::MaterialCast(quad); QSGTexture *layer = findRenderPassLayer(renderPassQuad->render_pass_id, m_sgObjects.renderPassLayers).data(); // cc::GLRenderer::DrawRenderPassQuad silently ignores missing render passes. diff --git a/src/core/dev_tools_http_handler_delegate_qt.cpp b/src/core/dev_tools_http_handler_delegate_qt.cpp index 793ed0981..1b19ed4a9 100644 --- a/src/core/dev_tools_http_handler_delegate_qt.cpp +++ b/src/core/dev_tools_http_handler_delegate_qt.cpp @@ -247,6 +247,11 @@ std::string DevToolsHttpHandlerDelegateQt::GetFrontendResource(const std::string return content::DevToolsFrontendHost::GetFrontendResource(path).as_string(); } +content::DevToolsExternalAgentProxyDelegate* DevToolsHttpHandlerDelegateQt::HandleWebSocketConnection(const std::string&) +{ + return 0; +} + base::DictionaryValue* DevToolsManagerDelegateQt::HandleCommand(DevToolsAgentHost *, base::DictionaryValue *) { return 0; diff --git a/src/core/dev_tools_http_handler_delegate_qt.h b/src/core/dev_tools_http_handler_delegate_qt.h index 0fe9ad0ce..2319696a6 100644 --- a/src/core/dev_tools_http_handler_delegate_qt.h +++ b/src/core/dev_tools_http_handler_delegate_qt.h @@ -69,6 +69,8 @@ public: std::string GetFrontendResource(const std::string&) Q_DECL_OVERRIDE; std::string GetPageThumbnailData(const GURL &url) Q_DECL_OVERRIDE; + content::DevToolsExternalAgentProxyDelegate* HandleWebSocketConnection(const std::string&) Q_DECL_OVERRIDE; + private: QString m_bindAddress; int m_port; diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp index 6d29af76a..454e1ff49 100644 --- a/src/core/download_manager_delegate_qt.cpp +++ b/src/core/download_manager_delegate_qt.cpp @@ -62,9 +62,15 @@ ASSERT_ENUMS_MATCH(content::DownloadItem::COMPLETE, BrowserContextAdapterClient: ASSERT_ENUMS_MATCH(content::DownloadItem::CANCELLED, BrowserContextAdapterClient::DownloadCancelled) ASSERT_ENUMS_MATCH(content::DownloadItem::INTERRUPTED, BrowserContextAdapterClient::DownloadInterrupted) +ASSERT_ENUMS_MATCH(content::SAVE_PAGE_TYPE_UNKNOWN, BrowserContextAdapterClient::UnknownSavePageFormat) +ASSERT_ENUMS_MATCH(content::SAVE_PAGE_TYPE_AS_ONLY_HTML, BrowserContextAdapterClient::SingleHtmlSaveFormat) +ASSERT_ENUMS_MATCH(content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML, BrowserContextAdapterClient::CompleteHtmlSaveFormat) +ASSERT_ENUMS_MATCH(content::SAVE_PAGE_TYPE_AS_MHTML, BrowserContextAdapterClient::MimeHtmlSaveFormat) + DownloadManagerDelegateQt::DownloadManagerDelegateQt(BrowserContextAdapter *contextAdapter) : m_contextAdapter(contextAdapter) , m_currentId(0) + , m_weakPtrFactory(this) { Q_ASSERT(m_contextAdapter); } @@ -147,6 +153,7 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(content::DownloadItem* i item->GetReceivedBytes(), mimeTypeString, suggestedFilePath, + BrowserContextAdapterClient::UnknownSavePageFormat, false /* accepted */ }; @@ -188,6 +195,58 @@ void DownloadManagerDelegateQt::GetSaveDir(content::BrowserContext* browser_cont *skip_dir_check = true; } +void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_contents, + const base::FilePath &suggested_path, + const base::FilePath::StringType &default_extension, + bool can_save_as_complete, + const content::SavePackagePathPickedCallback &callback) +{ + Q_UNUSED(default_extension); + Q_UNUSED(can_save_as_complete); + + QList<BrowserContextAdapterClient*> clients = m_contextAdapter->clients(); + if (clients.isEmpty()) + return; + + const QString suggestedFileName + = QFileInfo(toQt(suggested_path.AsUTF8Unsafe())).completeBaseName() + + QStringLiteral(".mhtml"); + const QDir defaultDownloadDirectory + = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation); + const QString suggestedFilePath = defaultDownloadDirectory.absoluteFilePath(suggestedFileName); + + BrowserContextAdapterClient::DownloadItemInfo info = { + m_currentId + 1, + toQt(web_contents->GetURL()), + content::DownloadItem::IN_PROGRESS, + 0, /* totalBytes */ + 0, /* receivedBytes */ + QStringLiteral("application/x-mimearchive"), + suggestedFilePath, + BrowserContextAdapterClient::MimeHtmlSaveFormat, + false /* accepted */ + }; + + Q_FOREACH (BrowserContextAdapterClient *client, clients) { + client->downloadRequested(info); + if (info.accepted) + break; + } + + if (!info.accepted) + return; + + callback.Run(toFilePath(info.path), static_cast<content::SavePageType>(info.savePageFormat), + base::Bind(&DownloadManagerDelegateQt::savePackageDownloadCreated, + m_weakPtrFactory.GetWeakPtr())); +} + +void DownloadManagerDelegateQt::savePackageDownloadCreated(content::DownloadItem *item) +{ + OnDownloadUpdated(item); + item->AddObserver(this); +} + void DownloadManagerDelegateQt::OnDownloadUpdated(content::DownloadItem *download) { QList<BrowserContextAdapterClient*> clients = m_contextAdapter->clients(); @@ -200,6 +259,7 @@ void DownloadManagerDelegateQt::OnDownloadUpdated(content::DownloadItem *downloa download->GetReceivedBytes(), toQt(download->GetMimeType()), QString(), + BrowserContextAdapterClient::UnknownSavePageFormat, true /* accepted */ }; diff --git a/src/core/download_manager_delegate_qt.h b/src/core/download_manager_delegate_qt.h index fea965749..700c2f5a7 100644 --- a/src/core/download_manager_delegate_qt.h +++ b/src/core/download_manager_delegate_qt.h @@ -38,6 +38,7 @@ #define DOWNLOAD_MANAGER_DELEGATE_QT_H #include "content/public/browser/download_manager_delegate.h" +#include <base/memory/weak_ptr.h> #include <QtCore/qcompilerdetection.h> // Needed for Q_DECL_OVERRIDE @@ -72,6 +73,12 @@ public: base::FilePath* website_save_dir, base::FilePath* download_save_dir, bool* skip_dir_check) Q_DECL_OVERRIDE; + void ChooseSavePath(content::WebContents *web_contents, + const base::FilePath &suggested_path, + const base::FilePath::StringType &default_extension, + bool can_save_as_complete, + const content::SavePackagePathPickedCallback &callback) Q_DECL_OVERRIDE; + void cancelDownload(quint32 downloadId); @@ -81,9 +88,11 @@ public: private: void cancelDownload(const content::DownloadTargetCallback& callback); + void savePackageDownloadCreated(content::DownloadItem *download); BrowserContextAdapter *m_contextAdapter; uint64 m_currentId; + base::WeakPtrFactory<DownloadManagerDelegateQt> m_weakPtrFactory; friend class DownloadManagerDelegateInstance; DISALLOW_COPY_AND_ASSIGN(DownloadManagerDelegateQt); diff --git a/src/core/javascript_dialog_manager_qt.cpp b/src/core/javascript_dialog_manager_qt.cpp index 24d426098..67f33327e 100644 --- a/src/core/javascript_dialog_manager_qt.cpp +++ b/src/core/javascript_dialog_manager_qt.cpp @@ -49,7 +49,7 @@ Q_STATIC_ASSERT_X(static_cast<int>(content::JAVASCRIPT_MESSAGE_TYPE_PROMPT) == s JavaScriptDialogManagerQt *JavaScriptDialogManagerQt::GetInstance() { - return Singleton<JavaScriptDialogManagerQt>::get(); + return base::Singleton<JavaScriptDialogManagerQt>::get(); } void JavaScriptDialogManagerQt::RunJavaScriptDialog(content::WebContents *webContents, const GURL &originUrl, const std::string &acceptLang, content::JavaScriptMessageType javascriptMessageType, const base::string16 &messageText, const base::string16 &defaultPromptText, const content::JavaScriptDialogManager::DialogClosedCallback &callback, bool *didSuppressMessage) diff --git a/src/core/media_capture_devices_dispatcher.cpp b/src/core/media_capture_devices_dispatcher.cpp index b31d22a76..f347e17c0 100644 --- a/src/core/media_capture_devices_dispatcher.cpp +++ b/src/core/media_capture_devices_dispatcher.cpp @@ -44,6 +44,7 @@ #include "javascript_dialog_manager_qt.h" #include "type_conversion.h" #include "web_contents_view_qt.h" +#include "web_engine_settings.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/media/desktop_streams_registry.h" @@ -54,6 +55,7 @@ #include "content/public/browser/notification_source.h" #include "content/public/browser/notification_types.h" #include "content/public/browser/web_contents.h" +#include "content/public/common/origin_util.h" #include "content/public/common/media_stream_request.h" #include "media/audio/audio_manager_base.h" #include "ui/base/l10n/l10n_util.h" @@ -187,7 +189,7 @@ void MediaCaptureDevicesDispatcher::handleMediaAccessPermissionResponse(content: MediaCaptureDevicesDispatcher *MediaCaptureDevicesDispatcher::GetInstance() { - return Singleton<MediaCaptureDevicesDispatcher>::get(); + return base::Singleton<MediaCaptureDevicesDispatcher>::get(); } MediaCaptureDevicesDispatcher::MediaCaptureDevicesDispatcher() @@ -292,10 +294,10 @@ void MediaCaptureDevicesDispatcher::processScreenCaptureAccessRequest(content::W { DCHECK_EQ(request.video_type, content::MEDIA_DESKTOP_VIDEO_CAPTURE); - // FIXME: expose through the settings once we have them - const bool screenCaptureEnabled = !qgetenv("QT_WEBENGINE_USE_EXPERIMENTAL_SCREEN_CAPTURE").isNull(); + WebContentsAdapterClient *adapterClient = WebContentsViewQt::from(static_cast<content::WebContentsImpl*>(webContents)->GetView())->client(); + const bool screenCaptureEnabled = adapterClient->webEngineSettings()->testAttribute(WebEngineSettings::ScreenCaptureEnabled); - const bool originIsSecure = request.security_origin.SchemeIsSecure(); + const bool originIsSecure = content::IsOriginSecure(request.security_origin); if (screenCaptureEnabled && originIsSecure) { diff --git a/src/core/media_capture_devices_dispatcher.h b/src/core/media_capture_devices_dispatcher.h index 500fe7644..0e51ebe6f 100644 --- a/src/core/media_capture_devices_dispatcher.h +++ b/src/core/media_capture_devices_dispatcher.h @@ -84,7 +84,7 @@ class MediaCaptureDevicesDispatcher : public content::MediaObserver, DesktopStreamsRegistry *getDesktopStreamsRegistry(); private: - friend struct DefaultSingletonTraits<MediaCaptureDevicesDispatcher>; + friend struct base::DefaultSingletonTraits<MediaCaptureDevicesDispatcher>; struct PendingAccessRequest { PendingAccessRequest(const content::MediaStreamRequest &request, diff --git a/src/core/network_delegate_qt.cpp b/src/core/network_delegate_qt.cpp index 6fdabcd4c..a80003a55 100644 --- a/src/core/network_delegate_qt.cpp +++ b/src/core/network_delegate_qt.cpp @@ -261,7 +261,15 @@ void NetworkDelegateQt::OnResponseStarted(net::URLRequest*) { } -void NetworkDelegateQt::OnRawBytesRead(const net::URLRequest&, int) +void NetworkDelegateQt::OnNetworkBytesReceived(const net::URLRequest&, int64_t) +{ +} + +void NetworkDelegateQt::OnNetworkBytesSent(const net::URLRequest&, int64_t) +{ +} + +void NetworkDelegateQt::OnURLRequestJobOrphaned(net::URLRequest*) { } diff --git a/src/core/network_delegate_qt.h b/src/core/network_delegate_qt.h index 41b5b98b6..ba2a9cd24 100644 --- a/src/core/network_delegate_qt.h +++ b/src/core/network_delegate_qt.h @@ -81,7 +81,9 @@ public: virtual int OnHeadersReceived(net::URLRequest*, const net::CompletionCallback&, const net::HttpResponseHeaders*, scoped_refptr<net::HttpResponseHeaders>*, GURL*) override; virtual void OnBeforeRedirect(net::URLRequest*, const GURL&) override; virtual void OnResponseStarted(net::URLRequest*) override; - virtual void OnRawBytesRead(const net::URLRequest&, int) override; + virtual void OnNetworkBytesReceived(const net::URLRequest&, int64_t) override; + virtual void OnNetworkBytesSent(const net::URLRequest&, int64_t) override; + virtual void OnURLRequestJobOrphaned(net::URLRequest*) override; virtual void OnCompleted(net::URLRequest*, bool) override; virtual void OnPACScriptError(int, const base::string16&) override; virtual net::NetworkDelegate::AuthRequiredResponse OnAuthRequired(net::URLRequest*, const net::AuthChallengeInfo&, const AuthCallback&, net::AuthCredentials*) override; diff --git a/src/core/ozone_platform_eglfs.cpp b/src/core/ozone_platform_eglfs.cpp index 834e41fdf..3ee2f1c4b 100644 --- a/src/core/ozone_platform_eglfs.cpp +++ b/src/core/ozone_platform_eglfs.cpp @@ -45,6 +45,7 @@ #include "ui/events/ozone/events_ozone.h" #include "ui/events/platform/platform_event_dispatcher.h" #include "ui/ozone/common/native_display_delegate_ozone.h" +#include "ui/ozone/common/stub_client_native_pixmap_factory.h" #include "ui/ozone/common/stub_overlay_manager.h" #include "ui/ozone/public/ozone_platform.h" #include "ui/ozone/public/cursor_factory_ozone.h" @@ -88,6 +89,7 @@ public: void Show() override { } void Hide() override { } void Close() override { } + void SetTitle(const base::string16&) override { } void SetCapture() override { } void ReleaseCapture() override { } void ToggleFullscreen() override { } @@ -97,7 +99,7 @@ public: void SetCursor(PlatformCursor) override { } void MoveCursorTo(const gfx::Point&) override { } void ConfineCursorToBounds(const gfx::Rect&) override { } - + PlatformImeController* GetPlatformImeController() override { return nullptr; } // PlatformEventDispatcher: bool CanDispatchEvent(const PlatformEvent& event) override; uint32_t DispatchEvent(const PlatformEvent& event) override; @@ -179,8 +181,17 @@ scoped_ptr<ui::NativeDisplayDelegate> OzonePlatformEglfs::CreateNativeDisplayDel return scoped_ptr<NativeDisplayDelegate>(new NativeDisplayDelegateOzone()); } +base::ScopedFD OzonePlatformEglfs::OpenClientNativePixmapDevice() const +{ + return base::ScopedFD(); +} + OzonePlatform* CreateOzonePlatformEglfs() { return new OzonePlatformEglfs; } +ClientNativePixmapFactory* CreateClientNativePixmapFactoryEglfs() { + return CreateStubClientNativePixmapFactory(); +} + void OzonePlatformEglfs::InitializeUI() { overlay_manager_.reset(new StubOverlayManager()); device_manager_ = CreateDeviceManager(); diff --git a/src/core/ozone_platform_eglfs.h b/src/core/ozone_platform_eglfs.h index 69ff2508f..10bd4d4d0 100644 --- a/src/core/ozone_platform_eglfs.h +++ b/src/core/ozone_platform_eglfs.h @@ -62,6 +62,7 @@ class OzonePlatformEglfs : public OzonePlatform { PlatformWindowDelegate* delegate, const gfx::Rect& bounds) override; virtual scoped_ptr<ui::NativeDisplayDelegate> CreateNativeDisplayDelegate() override; + virtual base::ScopedFD OpenClientNativePixmapDevice() const override; virtual ui::InputController* GetInputController() override; virtual scoped_ptr<ui::SystemInputInjector> CreateSystemInputInjector() override; virtual ui::OverlayManagerOzone* GetOverlayManager() override; diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp index b322e507e..19204b270 100644 --- a/src/core/permission_manager_qt.cpp +++ b/src/core/permission_manager_qt.cpp @@ -56,6 +56,10 @@ BrowserContextAdapter::PermissionType toQt(content::PermissionType type) case content::PermissionType::MIDI_SYSEX: case content::PermissionType::PUSH_MESSAGING: case content::PermissionType::PROTECTED_MEDIA_IDENTIFIER: + case content::PermissionType::MIDI: + case content::PermissionType::DURABLE_STORAGE: + case content::PermissionType::AUDIO_CAPTURE: + case content::PermissionType::VIDEO_CAPTURE: case content::PermissionType::NUM: break; } @@ -64,7 +68,8 @@ BrowserContextAdapter::PermissionType toQt(content::PermissionType type) PermissionManagerQt::PermissionManagerQt(BrowserContextAdapter *contextAdapter) : m_contextAdapter(contextAdapter) - , m_subscriberCount(0) + , m_requestIdCount(0) + , m_subscriberIdCount(0) { } @@ -85,60 +90,44 @@ void PermissionManagerQt::permissionRequestReply(const QUrl &origin, BrowserCont } else ++it; } - Q_FOREACH (const Subscriber &subscriber, m_subscribers) { + Q_FOREACH (const RequestOrSubscription &subscriber, m_subscribers) { if (subscriber.origin == origin && subscriber.type == type) subscriber.callback.Run(status); } } -void PermissionManagerQt::RequestPermission(content::PermissionType permission, +int PermissionManagerQt::RequestPermission(content::PermissionType permission, content::RenderFrameHost *frameHost, - int request_id, const GURL& requesting_origin, bool user_gesture, const base::Callback<void(content::PermissionStatus)>& callback) { Q_UNUSED(user_gesture); + int request_id = ++m_requestIdCount; BrowserContextAdapter::PermissionType permissionType = toQt(permission); if (permissionType == BrowserContextAdapter::UnsupportedPermission) { callback.Run(content::PERMISSION_STATUS_DENIED); - return; + return request_id; } content::WebContents *webContents = frameHost->GetRenderViewHost()->GetDelegate()->GetAsWebContents(); WebContentsDelegateQt* contentsDelegate = static_cast<WebContentsDelegateQt*>(webContents->GetDelegate()); Q_ASSERT(contentsDelegate); - Request request = { - request_id, + RequestOrSubscription request = { permissionType, toQt(requesting_origin), callback }; - m_requests.append(request); + m_requests.insert(request_id, request); if (permissionType == BrowserContextAdapter::GeolocationPermission) contentsDelegate->requestGeolocationPermission(request.origin); + return request_id; } -void PermissionManagerQt::CancelPermissionRequest(content::PermissionType permission, - content::RenderFrameHost *frameHost, - int request_id, - const GURL& requesting_origin) +void PermissionManagerQt::CancelPermissionRequest(int request_id) { - Q_UNUSED(frameHost); - const BrowserContextAdapter::PermissionType permissionType = toQt(permission); - if (permissionType == BrowserContextAdapter::UnsupportedPermission) - return; - // Should we add API to cancel permissions in the UI level? - const QUrl origin = toQt(requesting_origin); - auto it = m_requests.begin(); - while (it != m_requests.end()) { - if (it->id == request_id && it->type == permissionType && it->origin == origin) { - m_requests.erase(it); - return; - } - } - qWarning() << "PermissionManagerQt::CancelPermissionRequest called on unknown request" << request_id << origin << permissionType; + m_requests.remove(request_id); } content::PermissionStatus PermissionManagerQt::GetPermissionStatus( @@ -185,25 +174,20 @@ int PermissionManagerQt::SubscribePermissionStatusChange( const GURL& /*embedding_origin*/, const base::Callback<void(content::PermissionStatus)>& callback) { - Subscriber subscriber = { - m_subscriberCount++, + int subscriber_id = ++m_subscriberIdCount; + RequestOrSubscription subscriber = { toQt(permission), toQt(requesting_origin), callback }; - m_subscribers.append(subscriber); - return subscriber.id; + m_subscribers.insert(subscriber_id, subscriber); + return subscriber_id; } void PermissionManagerQt::UnsubscribePermissionStatusChange(int subscription_id) { - for (int i = 0; i < m_subscribers.count(); i++) { - if (m_subscribers[i].id == subscription_id) { - m_subscribers.removeAt(i); - return; - } - } - qWarning() << "PermissionManagerQt::UnsubscribePermissionStatusChange called on unknown subscription id" << subscription_id; + if (!m_subscribers.remove(subscription_id)) + qWarning() << "PermissionManagerQt::UnsubscribePermissionStatusChange called on unknown subscription id" << subscription_id; } } // namespace QtWebEngineCore diff --git a/src/core/permission_manager_qt.h b/src/core/permission_manager_qt.h index 6dfc60c39..5607ce889 100644 --- a/src/core/permission_manager_qt.h +++ b/src/core/permission_manager_qt.h @@ -56,19 +56,14 @@ public: void permissionRequestReply(const QUrl &origin, PermissionType type, bool reply); // content::PermissionManager implementation: - void RequestPermission( + int RequestPermission( content::PermissionType permission, content::RenderFrameHost* render_frame_host, - int request_id, const GURL& requesting_origin, bool user_gesture, const base::Callback<void(content::PermissionStatus)>& callback) override; - void CancelPermissionRequest( - content::PermissionType permission, - content::RenderFrameHost* render_frame_host, - int request_id, - const GURL& requesting_origin) override; + void CancelPermissionRequest(int request_id) override; content::PermissionStatus GetPermissionStatus( content::PermissionType permission, @@ -96,21 +91,15 @@ public: private: BrowserContextAdapter *m_contextAdapter; QHash<QPair<QUrl, PermissionType>, bool> m_permissions; - struct Request { - int id; - PermissionType type; - QUrl origin; - base::Callback<void(content::PermissionStatus)> callback; - }; - QVector<Request> m_requests; - struct Subscriber { - int id; + struct RequestOrSubscription { PermissionType type; QUrl origin; base::Callback<void(content::PermissionStatus)> callback; }; - int m_subscriberCount; - QVector<Subscriber> m_subscribers; + QHash<int, RequestOrSubscription> m_requests; + QHash<int, RequestOrSubscription> m_subscribers; + int m_requestIdCount; + int m_subscriberIdCount; }; diff --git a/src/core/proxy_config_service_qt.cpp b/src/core/proxy_config_service_qt.cpp index fc0959eef..21d10c27d 100644 --- a/src/core/proxy_config_service_qt.cpp +++ b/src/core/proxy_config_service_qt.cpp @@ -66,8 +66,8 @@ net::ProxyServer ProxyConfigServiceQt::fromQNetworkProxy(const QNetworkProxy &qt //================ Based on ChromeProxyConfigService ======================= -ProxyConfigServiceQt::ProxyConfigServiceQt(net::ProxyConfigService *baseService) - : m_baseService(baseService), +ProxyConfigServiceQt::ProxyConfigServiceQt(scoped_ptr<ProxyConfigService> baseService) + : m_baseService(baseService.release()), m_registeredObserver(false) { } diff --git a/src/core/proxy_config_service_qt.h b/src/core/proxy_config_service_qt.h index ee4263314..12cdc2505 100644 --- a/src/core/proxy_config_service_qt.h +++ b/src/core/proxy_config_service_qt.h @@ -54,7 +54,7 @@ public: static net::ProxyServer fromQNetworkProxy(const QNetworkProxy &); - explicit ProxyConfigServiceQt(net::ProxyConfigService *baseService); + explicit ProxyConfigServiceQt(scoped_ptr<ProxyConfigService> baseService); ~ProxyConfigServiceQt() override; // ProxyConfigService implementation: diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index fbfa12e91..cade9aa8a 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -160,30 +160,6 @@ static inline bool compareTouchPoints(const QTouchEvent::TouchPoint &lhs, const return lhs.state() < rhs.state(); } -static inline int flagsFromModifiers(Qt::KeyboardModifiers modifiers) -{ - int modifierFlags = ui::EF_NONE; -#if defined(Q_OS_OSX) - if (!qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { - if ((modifiers & Qt::ControlModifier) != 0) - modifierFlags |= ui::EF_COMMAND_DOWN; - if ((modifiers & Qt::MetaModifier) != 0) - modifierFlags |= ui::EF_CONTROL_DOWN; - } else -#endif - { - if ((modifiers & Qt::ControlModifier) != 0) - modifierFlags |= ui::EF_CONTROL_DOWN; - if ((modifiers & Qt::MetaModifier) != 0) - modifierFlags |= ui::EF_COMMAND_DOWN; - } - if ((modifiers & Qt::ShiftModifier) != 0) - modifierFlags |= ui::EF_SHIFT_DOWN; - if ((modifiers & Qt::AltModifier) != 0) - modifierFlags |= ui::EF_ALT_DOWN; - return modifierFlags; -} - static uint32 s_eventId = 0; class MotionEventQt : public ui::MotionEvent { public: @@ -376,7 +352,6 @@ content::BrowserAccessibilityManager* RenderWidgetHostViewQt::CreateBrowserAcces // Set focus to the associated View component. void RenderWidgetHostViewQt::Focus() { - m_host->SetInputMethodActive(true); if (!IsPopup()) m_delegate->setKeyboardFocus(); m_host->Focus(); @@ -556,13 +531,10 @@ void RenderWidgetHostViewQt::SetIsLoading(bool) // We use WebContentsDelegateQt::LoadingStateChanged to notify about loading state. } -void RenderWidgetHostViewQt::TextInputTypeChanged(ui::TextInputType type, ui::TextInputMode mode, bool can_compose_inline, int flags) +void RenderWidgetHostViewQt::TextInputStateChanged(const ViewHostMsg_TextInputState_Params ¶ms) { - Q_UNUSED(mode); - Q_UNUSED(can_compose_inline); - Q_UNUSED(flags); - m_currentInputType = type; - m_delegate->inputMethodStateChanged(static_cast<bool>(type)); + m_currentInputType = params.type; + m_delegate->inputMethodStateChanged(params.type != ui::TEXT_INPUT_TYPE_NONE); } void RenderWidgetHostViewQt::ImeCancelComposition() @@ -610,7 +582,7 @@ void RenderWidgetHostViewQt::SelectionBoundsChanged(const ViewHostMsg_SelectionB m_cursorRect = QRect(caretRect.x(), caretRect.y(), caretRect.width(), caretRect.height()); } -void RenderWidgetHostViewQt::CopyFromCompositingSurface(const gfx::Rect& src_subrect, const gfx::Size& dst_size, content::ReadbackRequestCallback& callback, const SkColorType color_type) +void RenderWidgetHostViewQt::CopyFromCompositingSurface(const gfx::Rect& src_subrect, const gfx::Size& dst_size, const content::ReadbackRequestCallback& callback, const SkColorType color_type) { NOTIMPLEMENTED(); Q_UNUSED(src_subrect); @@ -637,7 +609,10 @@ bool RenderWidgetHostViewQt::HasAcceleratedSurface(const gfx::Size&) void RenderWidgetHostViewQt::OnSwapCompositorFrame(uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame) { + bool scrollOffsetChanged = (m_lastScrollOffset != frame->metadata.root_scroll_offset); + bool contentsSizeChanged = (m_lastContentsSize != frame->metadata.root_layer_size); m_lastScrollOffset = frame->metadata.root_scroll_offset; + m_lastContentsSize = frame->metadata.root_layer_size; Q_ASSERT(!m_needsDelegatedFrameAck); m_needsDelegatedFrameAck = true; m_pendingOutputSurfaceId = output_surface_id; @@ -657,6 +632,11 @@ void RenderWidgetHostViewQt::OnSwapCompositorFrame(uint32 output_surface_id, sco m_adapterClient->loadVisuallyCommitted(); m_didFirstVisuallyNonEmptyLayout = false; } + + if (scrollOffsetChanged) + m_adapterClient->updateScrollPosition(toQt(m_lastScrollOffset)); + if (contentsSizeChanged) + m_adapterClient->updateContentsSize(toQt(m_lastContentsSize)); } void RenderWidgetHostViewQt::GetScreenInfo(blink::WebScreenInfo* results) @@ -679,9 +659,13 @@ gfx::Rect RenderWidgetHostViewQt::GetBoundsInRootWindow() return gfx::Rect(r.x(), r.y(), r.width(), r.height()); } -gfx::GLSurfaceHandle RenderWidgetHostViewQt::GetCompositingSurface() +void RenderWidgetHostViewQt::ClearCompositorFrame() { - return gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NULL_TRANSPORT); +} + +bool RenderWidgetHostViewQt::GetScreenColorProfile(std::vector<char>*) +{ + return false; } void RenderWidgetHostViewQt::SelectionChanged(const base::string16 &text, size_t offset, const gfx::Range &range) diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h index 274138dcf..1669330ec 100644 --- a/src/core/render_widget_host_view_qt.h +++ b/src/core/render_widget_host_view_qt.h @@ -132,22 +132,23 @@ public: virtual void MovePluginWindows(const std::vector<content::WebPluginGeometry>&) Q_DECL_OVERRIDE; virtual void UpdateCursor(const content::WebCursor&) Q_DECL_OVERRIDE; virtual void SetIsLoading(bool) Q_DECL_OVERRIDE; - virtual void TextInputTypeChanged(ui::TextInputType type, ui::TextInputMode mode, bool can_compose_inline, int flags) Q_DECL_OVERRIDE; + virtual void TextInputStateChanged(const ViewHostMsg_TextInputState_Params&) Q_DECL_OVERRIDE; virtual void ImeCancelComposition() Q_DECL_OVERRIDE; virtual void ImeCompositionRangeChanged(const gfx::Range&, const std::vector<gfx::Rect>&) Q_DECL_OVERRIDE; virtual void RenderProcessGone(base::TerminationStatus, int) Q_DECL_OVERRIDE; virtual void Destroy() Q_DECL_OVERRIDE; virtual void SetTooltipText(const base::string16 &tooltip_text) Q_DECL_OVERRIDE; virtual void SelectionBoundsChanged(const ViewHostMsg_SelectionBounds_Params&) Q_DECL_OVERRIDE; - virtual void CopyFromCompositingSurface(const gfx::Rect& src_subrect, const gfx::Size& dst_size, content::ReadbackRequestCallback& callback, const SkColorType color_type) Q_DECL_OVERRIDE; + virtual void CopyFromCompositingSurface(const gfx::Rect& src_subrect, const gfx::Size& dst_size, const content::ReadbackRequestCallback& callback, const SkColorType preferred_color_type) Q_DECL_OVERRIDE; virtual void CopyFromCompositingSurfaceToVideoFrame(const gfx::Rect& src_subrect, const scoped_refptr<media::VideoFrame>& target, const base::Callback<void(bool)>& callback) Q_DECL_OVERRIDE; virtual bool CanCopyToVideoFrame() const Q_DECL_OVERRIDE; virtual bool HasAcceleratedSurface(const gfx::Size&) Q_DECL_OVERRIDE; virtual void OnSwapCompositorFrame(uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame) Q_DECL_OVERRIDE; virtual void GetScreenInfo(blink::WebScreenInfo* results) Q_DECL_OVERRIDE; virtual gfx::Rect GetBoundsInRootWindow() Q_DECL_OVERRIDE; - virtual gfx::GLSurfaceHandle GetCompositingSurface() Q_DECL_OVERRIDE; virtual void ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch, content::InputEventAckState ack_result) Q_DECL_OVERRIDE; + virtual void ClearCompositorFrame() Q_DECL_OVERRIDE; + virtual bool GetScreenColorProfile(std::vector<char>*) Q_DECL_OVERRIDE; // Overridden from RenderWidgetHostViewBase. virtual void SelectionChanged(const base::string16 &text, size_t offset, const gfx::Range &range) Q_DECL_OVERRIDE; @@ -202,6 +203,8 @@ public: #endif // QT_NO_ACCESSIBILITY void didFirstVisuallyNonEmptyLayout(); + gfx::SizeF lastContentsSize() const { return m_lastContentsSize; } + private: void sendDelegatedFrameAck(); void processMotionEvent(const ui::MotionEvent &motionEvent); @@ -235,6 +238,7 @@ private: bool m_initPending; gfx::Vector2dF m_lastScrollOffset; + gfx::SizeF m_lastContentsSize; }; } // namespace QtWebEngineCore diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp index 261b9c581..2d36d71bd 100644 --- a/src/core/renderer/content_renderer_client_qt.cpp +++ b/src/core/renderer/content_renderer_client_qt.cpp @@ -76,7 +76,6 @@ ContentRendererClientQt::~ContentRendererClientQt() void ContentRendererClientQt::RenderThreadStarted() { content::RenderThread *renderThread = content::RenderThread::Get(); - renderThread->RegisterExtension(WebChannelIPCTransport::getV8Extension()); m_visitedLinkSlave.reset(new visitedlink::VisitedLinkSlave); m_webCacheObserver.reset(new web_cache::WebCacheRenderProcessObserver()); renderThread->AddObserver(m_visitedLinkSlave.data()); @@ -120,7 +119,7 @@ bool ContentRendererClientQt::ShouldSuppressErrorPage(content::RenderFrame *fram void ContentRendererClientQt::GetNavigationErrorStrings(content::RenderView* renderView, blink::WebFrame *frame, const blink::WebURLRequest &failedRequest, const blink::WebURLError &error, std::string *errorHtml, base::string16 *errorDescription) { Q_UNUSED(frame) - const bool isPost = base::EqualsASCII(failedRequest.httpMethod(), "POST"); + const bool isPost = QByteArray::fromStdString(failedRequest.httpMethod().utf8()) == QByteArrayLiteral("POST"); if (errorHtml) { // Use a local error page. @@ -131,7 +130,7 @@ void ContentRendererClientQt::GetNavigationErrorStrings(content::RenderView* ren // TODO(elproxy): We could potentially get better diagnostics here by first calling // NetErrorHelper::GetErrorStringsForDnsProbe, but that one is harder to untangle. LocalizedError::GetStrings(error.reason, error.domain.utf8(), error.unreachableURL, isPost - , error.staleCopyInCache && !isPost, locale, renderView->GetAcceptLanguages() + , error.staleCopyInCache && !isPost, false, locale, renderView->GetAcceptLanguages() , scoped_ptr<error_page::ErrorPageParams>(), &errorStrings); resourceId = IDR_NET_ERROR_HTML; 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 8e68d1682..c0df03382 100644 --- a/src/core/renderer/pepper/pepper_flash_renderer_host_qt.cpp +++ b/src/core/renderer/pepper/pepper_flash_renderer_host_qt.cpp @@ -65,8 +65,8 @@ #include "third_party/skia/include/core/SkMatrix.h" #include "third_party/skia/include/core/SkPaint.h" #include "third_party/skia/include/core/SkPoint.h" -#include "third_party/skia/include/core/SkTemplates.h" #include "third_party/skia/include/core/SkTypeface.h" +#include "third_party/skia/include/private/SkTemplates.h" #include "ui/gfx/geometry/rect.h" #include "url/gurl.h" @@ -278,7 +278,7 @@ int32_t PepperFlashRendererHostQt::OnNavigate( bool rejected = false; while (header_iter.GetNext()) { std::string lower_case_header_name = - base::StringToLowerASCII(header_iter.name()); + base::ToLowerASCII(header_iter.name()); if (!IsSimpleHeader(lower_case_header_name, header_iter.values())) { rejected = true; diff --git a/src/core/renderer/user_script_controller.cpp b/src/core/renderer/user_script_controller.cpp index 729500341..4391862a7 100644 --- a/src/core/renderer/user_script_controller.cpp +++ b/src/core/renderer/user_script_controller.cpp @@ -92,7 +92,7 @@ void UserScriptController::RenderViewObserverHelper::runScripts(UserScriptData:: continue; blink::WebScriptSource source(blink::WebString::fromUTF8(script.source), script.url); if (script.worldId) - frame->executeScriptInIsolatedWorld(script.worldId, &source, /*numSources = */1, /*contentScriptExtentsionGroup = */ 1); + frame->executeScriptInIsolatedWorld(script.worldId, &source, /*numSources = */1, /*contentScriptExtentsionGroup = */ 0); else frame->executeScript(source); } diff --git a/src/core/renderer/web_channel_ipc_transport.cpp b/src/core/renderer/web_channel_ipc_transport.cpp index 3d844bf0d..12acd348e 100644 --- a/src/core/renderer/web_channel_ipc_transport.cpp +++ b/src/core/renderer/web_channel_ipc_transport.cpp @@ -42,6 +42,10 @@ #include "common/qt_messages.h" #include "content/public/renderer/render_view.h" +#include "gin/arguments.h" +#include "gin/handle.h" +#include "gin/object_template_builder.h" +#include "gin/wrappable.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" #include "third_party/WebKit/public/web/WebView.h" #include "v8/include/v8.h" @@ -50,34 +54,22 @@ namespace QtWebEngineCore { -static const char kWebChannelTransportExtensionName[] = "v8/WebChannelTransport"; - -static const char kWebChannelTransportApi[] = - "if (typeof(qt) === 'undefined')" \ - " qt = {};" \ - "if (typeof(qt.webChannelTransport) === 'undefined')" \ - " qt.webChannelTransport = {};" \ - "qt.webChannelTransport.send = function(message) {" \ - " native function NativeQtSendMessage();" \ - " NativeQtSendMessage(message);" \ - "};"; - -class WebChannelTransportExtension : public v8::Extension { +class WebChannelTransport : public gin::Wrappable<WebChannelTransport> { public: - static content::RenderView *GetRenderView(); - - WebChannelTransportExtension() : v8::Extension(kWebChannelTransportExtensionName, kWebChannelTransportApi) - { - } - - virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(v8::Isolate* isolate, v8::Handle<v8::String> name) Q_DECL_OVERRIDE; - - static void NativeQtSendMessage(const v8::FunctionCallbackInfo<v8::Value>& args) + static gin::WrapperInfo kWrapperInfo; + static void Install(blink::WebFrame *frame); +private: + content::RenderView *GetRenderView(v8::Isolate *isolate); + WebChannelTransport() { } + virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate *isolate) override; + + void NativeQtSendMessage(gin::Arguments *args) { - content::RenderView *renderView = GetRenderView(); - if (!renderView || args.Length() != 1) + content::RenderView *renderView = GetRenderView(args->isolate()); + if (!renderView || args->Length() != 1) return; - v8::Handle<v8::Value> val = args[0]; + v8::Handle<v8::Value> val; + args->GetNext(&val); if (!val->IsString() && !val->IsStringObject()) return; v8::String::Utf8Value utf8(val->ToString()); @@ -91,11 +83,37 @@ public: const char *rawData = doc.rawData(&size); renderView->Send(new WebChannelIPCTransportHost_SendMessage(renderView->GetRoutingID(), std::vector<char>(rawData, rawData + size))); } + + DISALLOW_COPY_AND_ASSIGN(WebChannelTransport); }; -content::RenderView *WebChannelTransportExtension::GetRenderView() +gin::WrapperInfo WebChannelTransport::kWrapperInfo = { gin::kEmbedderNativeGin }; + +void WebChannelTransport::Install(blink::WebFrame *frame) +{ + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope handleScope(isolate); + v8::Handle<v8::Context> context = frame->mainWorldScriptContext(); + v8::Context::Scope contextScope(context); + + gin::Handle<WebChannelTransport> transport = gin::CreateHandle(isolate, new WebChannelTransport); + v8::Handle<v8::Object> global = context->Global(); + v8::Handle<v8::Object> qt = global->Get(gin::StringToV8(isolate, "qt"))->ToObject(); + if (qt.IsEmpty()) { + qt = v8::Object::New(isolate); + global->Set(gin::StringToV8(isolate, "qt"), qt); + } + qt->Set(gin::StringToV8(isolate, "webChannelTransport"), transport.ToV8()); +} + +gin::ObjectTemplateBuilder WebChannelTransport::GetObjectTemplateBuilder(v8::Isolate *isolate) +{ + return gin::Wrappable<WebChannelTransport>::GetObjectTemplateBuilder(isolate).SetMethod("send", &WebChannelTransport::NativeQtSendMessage); +} + +content::RenderView *WebChannelTransport::GetRenderView(v8::Isolate *isolate) { - blink::WebLocalFrame *webframe = blink::WebLocalFrame::frameForCurrentContext(); + blink::WebLocalFrame *webframe = blink::WebLocalFrame::frameForContext(isolate->GetCurrentContext()); DCHECK(webframe) << "There should be an active frame since we just got a native function called."; if (!webframe) return 0; @@ -107,17 +125,17 @@ content::RenderView *WebChannelTransportExtension::GetRenderView() return content::RenderView::FromWebView(webview); } -v8::Handle<v8::FunctionTemplate> WebChannelTransportExtension::GetNativeFunctionTemplate(v8::Isolate *isolate, v8::Handle<v8::String> name) +WebChannelIPCTransport::WebChannelIPCTransport(content::RenderView *renderView) + : content::RenderViewObserver(renderView) { - if (name->Equals(v8::String::NewFromUtf8(isolate, "NativeQtSendMessage"))) - return v8::FunctionTemplate::New(isolate, NativeQtSendMessage); - - return v8::Handle<v8::FunctionTemplate>(); } -WebChannelIPCTransport::WebChannelIPCTransport(content::RenderView *renderView) - : content::RenderViewObserver(renderView) +void WebChannelIPCTransport::installExtension() { + blink::WebView *webView = render_view()->GetWebView(); + if (!webView) + return; + WebChannelTransport::Install(webView->mainFrame()); } void WebChannelIPCTransport::dispatchWebChannelMessage(const std::vector<char> &binaryJSON) @@ -137,13 +155,13 @@ void WebChannelIPCTransport::dispatchWebChannelMessage(const std::vector<char> & v8::Context::Scope contextScope(context); v8::Handle<v8::Object> global(context->Global()); - v8::Handle<v8::Value> qtObjectValue(global->Get(v8::String::NewFromUtf8(isolate, "qt"))); + v8::Handle<v8::Value> qtObjectValue(global->Get(gin::StringToV8(isolate, "qt"))); if (!qtObjectValue->IsObject()) return; - v8::Handle<v8::Value> webChannelObjectValue(qtObjectValue->ToObject()->Get(v8::String::NewFromUtf8(isolate, "webChannelTransport"))); + v8::Handle<v8::Value> webChannelObjectValue(qtObjectValue->ToObject()->Get(gin::StringToV8(isolate, "webChannelTransport"))); if (!webChannelObjectValue->IsObject()) return; - v8::Handle<v8::Value> onmessageCallbackValue(webChannelObjectValue->ToObject()->Get(v8::String::NewFromUtf8(isolate, "onmessage"))); + v8::Handle<v8::Value> onmessageCallbackValue(webChannelObjectValue->ToObject()->Get(gin::StringToV8(isolate, "onmessage"))); if (!onmessageCallbackValue->IsFunction()) { qWarning("onmessage is not a callable property of qt.webChannelTransport. Some things might not work as expected."); return; @@ -161,15 +179,11 @@ void WebChannelIPCTransport::dispatchWebChannelMessage(const std::vector<char> & frame->callFunctionEvenIfScriptDisabled(callback, webChannelObjectValue->ToObject(), argc, argv); } -v8::Extension *WebChannelIPCTransport::getV8Extension() -{ - return new WebChannelTransportExtension; -} - bool WebChannelIPCTransport::OnMessageReceived(const IPC::Message &message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(WebChannelIPCTransport, message) + IPC_MESSAGE_HANDLER(WebChannelIPCTransport_Install, installExtension) IPC_MESSAGE_HANDLER(WebChannelIPCTransport_Message, dispatchWebChannelMessage) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() diff --git a/src/core/renderer/web_channel_ipc_transport.h b/src/core/renderer/web_channel_ipc_transport.h index 69a02f7ea..ba378f440 100644 --- a/src/core/renderer/web_channel_ipc_transport.h +++ b/src/core/renderer/web_channel_ipc_transport.h @@ -49,12 +49,11 @@ namespace QtWebEngineCore { class WebChannelIPCTransport : public content::RenderViewObserver { public: - static v8::Extension* getV8Extension(); - WebChannelIPCTransport(content::RenderView *); private: void dispatchWebChannelMessage(const std::vector<char> &binaryJSON); + void installExtension(); virtual bool OnMessageReceived(const IPC::Message &message) Q_DECL_OVERRIDE; }; diff --git a/src/core/resources/resources.gyp b/src/core/resources/resources.gyp index 143f21f9d..157b78780 100644 --- a/src/core/resources/resources.gyp +++ b/src/core/resources/resources.gyp @@ -17,6 +17,7 @@ '<(chromium_src_dir)/content/app/strings/content_strings.gyp:content_strings', '<(chromium_src_dir)/blink/public/blink_resources.gyp:blink_resources', '<(chromium_src_dir)/content/browser/devtools/devtools_resources.gyp:devtools_resources', + '<(chromium_src_dir)/components/components_strings.gyp:components_strings', '../chrome_qt.gyp:chrome_resources', ], 'targets': [ diff --git a/src/core/type_conversion.cpp b/src/core/type_conversion.cpp new file mode 100644 index 000000000..99a7da099 --- /dev/null +++ b/src/core/type_conversion.cpp @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2015 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "type_conversion.h" + +#include <ui/events/event_constants.h> +#include <ui/gfx/image/image_skia.h> +#include <QtCore/qcoreapplication.h> + +namespace QtWebEngineCore { + +QImage toQImage(const SkBitmap &bitmap) +{ + QImage image; + switch (bitmap.colorType()) { + case kUnknown_SkColorType: + break; + case kAlpha_8_SkColorType: + image = toQImage(bitmap, QImage::Format_Alpha8); + break; + case kRGB_565_SkColorType: + image = toQImage(bitmap, QImage::Format_RGB16); + break; + case kARGB_4444_SkColorType: + switch (bitmap.alphaType()) { + case kUnknown_SkAlphaType: + break; + case kUnpremul_SkAlphaType: + // not supported - treat as opaque + case kOpaque_SkAlphaType: + image = toQImage(bitmap, QImage::Format_RGB444); + break; + case kPremul_SkAlphaType: + image = toQImage(bitmap, QImage::Format_ARGB4444_Premultiplied); + break; + } + break; + case kRGBA_8888_SkColorType: + switch (bitmap.alphaType()) { + case kUnknown_SkAlphaType: + break; + case kOpaque_SkAlphaType: + image = toQImage(bitmap, QImage::Format_RGBX8888); + break; + case kPremul_SkAlphaType: + image = toQImage(bitmap, QImage::Format_RGBA8888_Premultiplied); + break; + case kUnpremul_SkAlphaType: + image = toQImage(bitmap, QImage::Format_RGBA8888); + break; + } + break; + case kBGRA_8888_SkColorType: + // we are assuming little-endian arch here. + switch (bitmap.alphaType()) { + case kUnknown_SkAlphaType: + break; + case kOpaque_SkAlphaType: + image = toQImage(bitmap, QImage::Format_RGB32); + break; + case kPremul_SkAlphaType: + image = toQImage(bitmap, QImage::Format_ARGB32_Premultiplied); + break; + case kUnpremul_SkAlphaType: + image = toQImage(bitmap, QImage::Format_ARGB32); + break; + } + break; + case kIndex_8_SkColorType: { + image = toQImage(bitmap, QImage::Format_Indexed8); + SkColorTable *skTable = bitmap.getColorTable(); + if (skTable) { + QVector<QRgb> qTable(skTable->count()); + for (int i = 0; i < skTable->count(); ++i) + qTable[i] = (*skTable)[i]; + image.setColorTable(qTable); + } + break; + } + case kGray_8_SkColorType: + image = toQImage(bitmap, QImage::Format_Grayscale8); + break; + } + return image; +} + +QImage toQImage(const gfx::ImageSkiaRep &imageSkiaRep) +{ + QImage image = toQImage(imageSkiaRep.sk_bitmap()); + if (!image.isNull() && imageSkiaRep.scale() != 1.0f) + image.setDevicePixelRatio(imageSkiaRep.scale()); + return image; +} + +int flagsFromModifiers(Qt::KeyboardModifiers modifiers) +{ + int modifierFlags = ui::EF_NONE; +#if defined(Q_OS_OSX) + if (!qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { + if ((modifiers & Qt::ControlModifier) != 0) + modifierFlags |= ui::EF_COMMAND_DOWN; + if ((modifiers & Qt::MetaModifier) != 0) + modifierFlags |= ui::EF_CONTROL_DOWN; + } else +#endif + { + if ((modifiers & Qt::ControlModifier) != 0) + modifierFlags |= ui::EF_CONTROL_DOWN; + if ((modifiers & Qt::MetaModifier) != 0) + modifierFlags |= ui::EF_COMMAND_DOWN; + } + if ((modifiers & Qt::ShiftModifier) != 0) + modifierFlags |= ui::EF_SHIFT_DOWN; + if ((modifiers & Qt::AltModifier) != 0) + modifierFlags |= ui::EF_ALT_DOWN; + return modifierFlags; +} + + +} // namespace QtWebEngineCore diff --git a/src/core/type_conversion.h b/src/core/type_conversion.h index eb874a26d..5cf7267f2 100644 --- a/src/core/type_conversion.h +++ b/src/core/type_conversion.h @@ -46,6 +46,7 @@ #include <QRect> #include <QString> #include <QUrl> +#include <base/strings/nullable_string16.h> #include "base/files/file_path.h" #include "base/time/time.h" #include "content/public/common/file_chooser_file_info.h" @@ -55,8 +56,13 @@ #include "third_party/skia/include/core/SkPixelRef.h" #include "third_party/skia/include/utils/SkMatrix44.h" #include "ui/gfx/geometry/rect.h" +#include "ui/gfx/geometry/rect_f.h" #include "url/gurl.h" +namespace gfx { +class ImageSkiaRep; +} + namespace QtWebEngineCore { inline QString toQt(const base::string16 &string) @@ -82,6 +88,11 @@ inline base::string16 toString16(const QString &qString) #endif } +inline base::NullableString16 toNullableString16(const QString &qString) +{ + return base::NullableString16(toString16(qString), qString.isNull()); +} + inline QUrl toQt(const GURL &url) { return QUrl(QString::fromStdString(url.spec())); @@ -97,6 +108,11 @@ inline QPoint toQt(const gfx::Point &point) return QPoint(point.x(), point.y()); } +inline QPointF toQt(const gfx::Vector2dF &point) +{ + return QPointF(point.x(), point.y()); +} + inline gfx::Point toGfx(const QPoint& point) { return gfx::Point(point.x(), point.y()); @@ -143,6 +159,9 @@ inline QImage toQImage(const SkBitmap &bitmap, QImage::Format format) return QImage((uchar *)pixelRef->pixels(), bitmap.width(), bitmap.height(), format); } +QImage toQImage(const SkBitmap &bitmap); +QImage toQImage(const gfx::ImageSkiaRep &imageSkiaRep); + inline QMatrix4x4 toQt(const SkMatrix44 &m) { QMatrix4x4 qtMatrix( @@ -226,6 +245,8 @@ inline std::vector<T> toVector(const QStringList &fileList) return selectedFiles; } +int flagsFromModifiers(Qt::KeyboardModifiers modifiers); + } // namespace QtWebEngineCore #endif // TYPE_CONVERSION_H diff --git a/src/core/url_request_context_getter_qt.cpp b/src/core/url_request_context_getter_qt.cpp index 26e2633d8..ed3378b21 100644 --- a/src/core/url_request_context_getter_qt.cpp +++ b/src/core/url_request_context_getter_qt.cpp @@ -45,6 +45,7 @@ #include "content/public/common/content_switches.h" #include "net/base/cache_type.h" #include "net/cert/cert_verifier.h" +#include "net/disk_cache/disk_cache.h" #include "net/dns/host_resolver.h" #include "net/dns/mapped_host_resolver.h" #include "net/http/http_auth_handler_factory.h" @@ -177,7 +178,7 @@ void URLRequestContextGetterQt::generateStorage() m_dhcpProxyScriptFetcherFactory.reset(new net::DhcpProxyScriptFetcherFactory); m_storage->set_proxy_service(net::CreateProxyServiceUsingV8ProxyResolver( - proxyConfigService, + scoped_ptr<net::ProxyConfigService>(proxyConfigService), new net::ProxyScriptFetcherImpl(m_urlRequestContext.get()), m_dhcpProxyScriptFetcherFactory->Create(m_urlRequestContext.get()), host_resolver.get(), @@ -185,7 +186,7 @@ void URLRequestContextGetterQt::generateStorage() m_networkDelegate.get())); m_storage->set_ssl_config_service(new net::SSLConfigServiceDefaults); - m_storage->set_transport_security_state(new net::TransportSecurityState()); + m_storage->set_transport_security_state(scoped_ptr<net::TransportSecurityState>(new net::TransportSecurityState())); m_storage->set_http_auth_handler_factory(net::HttpAuthHandlerFactory::CreateDefault(host_resolver.get())); m_storage->set_http_server_properties(scoped_ptr<net::HttpServerProperties>(new net::HttpServerPropertiesImpl)); @@ -283,7 +284,7 @@ void URLRequestContextGetterQt::generateUserAgent() Q_ASSERT(m_urlRequestContext); Q_ASSERT(m_storage); - m_storage->set_http_user_agent_settings(new HttpUserAgentSettingsQt(m_browserContext)); + m_storage->set_http_user_agent_settings(scoped_ptr<net::HttpUserAgentSettings>(new HttpUserAgentSettingsQt(m_browserContext))); } void URLRequestContextGetterQt::updateHttpCache() @@ -382,10 +383,27 @@ void URLRequestContextGetterQt::generateHttpCache() } else cache = new net::HttpCache(network_session, main_backend); - m_storage->set_http_transaction_factory(cache); + m_storage->set_http_transaction_factory(scoped_ptr<net::HttpCache>(cache)); m_updateHttpCache = 0; } +void URLRequestContextGetterQt::clearHttpCache() +{ + if (m_urlRequestContext) + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestContextGetterQt::clearCurrentCacheBackend, this)); +} + +static void doomCallback(int error_code) { Q_UNUSED(error_code); } + +void URLRequestContextGetterQt::clearCurrentCacheBackend() +{ + if (m_urlRequestContext->http_transaction_factory() && m_urlRequestContext->http_transaction_factory()->GetCache()) { + disk_cache::Backend *backend = m_urlRequestContext->http_transaction_factory()->GetCache()->GetCurrentBackend(); + if (backend) + backend->DoomAllEntries(base::Bind(&doomCallback)); + } +} + void URLRequestContextGetterQt::generateJobFactory() { Q_ASSERT(m_urlRequestContext); @@ -397,22 +415,22 @@ void URLRequestContextGetterQt::generateJobFactory() // Chromium has a few protocol handlers ready for us, only pick blob: and throw away the rest. content::ProtocolHandlerMap::iterator it = m_protocolHandlers.find(url::kBlobScheme); Q_ASSERT(it != m_protocolHandlers.end()); - jobFactory->SetProtocolHandler(it->first, it->second.release()); + jobFactory->SetProtocolHandler(it->first, scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(it->second.release())); m_protocolHandlers.clear(); } - jobFactory->SetProtocolHandler(url::kDataScheme, new net::DataProtocolHandler()); - jobFactory->SetProtocolHandler(url::kFileScheme, new net::FileProtocolHandler( + jobFactory->SetProtocolHandler(url::kDataScheme, scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(new net::DataProtocolHandler())); + jobFactory->SetProtocolHandler(url::kFileScheme, scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(new net::FileProtocolHandler( content::BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior( - base::SequencedWorkerPool::SKIP_ON_SHUTDOWN))); - jobFactory->SetProtocolHandler(kQrcSchemeQt, new QrcProtocolHandlerQt()); + base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)))); + jobFactory->SetProtocolHandler(kQrcSchemeQt, scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(new QrcProtocolHandlerQt())); jobFactory->SetProtocolHandler(url::kFtpScheme, - new net::FtpProtocolHandler(new net::FtpNetworkLayer(m_urlRequestContext->host_resolver()))); + 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(), new CustomProtocolHandler(it.value())); + jobFactory->SetProtocolHandler(it.key().toStdString(), scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(new CustomProtocolHandler(it.value()))); // Set up interceptors in the reverse order. scoped_ptr<net::URLRequestJobFactory> topJobFactory = jobFactory.Pass(); diff --git a/src/core/url_request_context_getter_qt.h b/src/core/url_request_context_getter_qt.h index f61e4f09b..3c0a2ee19 100644 --- a/src/core/url_request_context_getter_qt.h +++ b/src/core/url_request_context_getter_qt.h @@ -77,6 +77,7 @@ public: void updateUserAgent(); void updateCookieStore(); void updateHttpCache(); + void clearHttpCache(); private: virtual ~URLRequestContextGetterQt(); @@ -87,6 +88,7 @@ private: void generateHttpCache(); void generateUserAgent(); void generateJobFactory(); + void clearCurrentCacheBackend(); void cancelAllUrlRequests(); net::HttpNetworkSession::Params generateNetworkSessionParams(); diff --git a/src/core/web_channel_ipc_transport_host.cpp b/src/core/web_channel_ipc_transport_host.cpp index ecc49ab5f..800e78308 100644 --- a/src/core/web_channel_ipc_transport_host.cpp +++ b/src/core/web_channel_ipc_transport_host.cpp @@ -50,6 +50,7 @@ WebChannelIPCTransportHost::WebChannelIPCTransportHost(content::WebContents *con : QWebChannelAbstractTransport(parent) , content::WebContentsObserver(contents) { + Send(new WebChannelIPCTransport_Install(routing_id())); } WebChannelIPCTransportHost::~WebChannelIPCTransportHost() diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index 608dbf7e7..fc77bdb9d 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -44,6 +44,7 @@ #include "browser_accessibility_qt.h" #include "browser_context_adapter.h" #include "browser_context_qt.h" +#include "download_manager_delegate_qt.h" #include "media_capture_devices_dispatcher.h" #include "qwebenginecallback_p.h" #include "render_view_observer_host_qt.h" @@ -54,6 +55,7 @@ #include "web_engine_context.h" #include "web_engine_settings.h" +#include <base/run_loop.h> #include "base/values.h" #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" @@ -64,6 +66,7 @@ #include "content/public/browser/navigation_entry.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/favicon_status.h" +#include <content/public/common/drop_data.h> #include "content/public/common/page_state.h" #include "content/public/common/page_zoom.h" #include "content/public/common/renderer_preferences.h" @@ -76,7 +79,10 @@ #include <QStringList> #include <QStyleHints> #include <QVariant> +#include <QtCore/qmimedata.h> #include <QtGui/qaccessible.h> +#include <QtGui/qdrag.h> +#include <QtGui/qpixmap.h> #include <QtWebChannel/QWebChannel> namespace QtWebEngineCore { @@ -164,7 +170,8 @@ static QVariant fromJSValue(const base::Value *result) static void callbackOnEvaluateJS(WebContentsAdapterClient *adapterClient, quint64 requestId, const base::Value *result) { - adapterClient->didRunJavaScript(requestId, fromJSValue(result)); + if (requestId) + adapterClient->didRunJavaScript(requestId, fromJSValue(result)); } static content::WebContents *createBlankWebContents(WebContentsAdapterClient *adapterClient, content::BrowserContext *browserContext) @@ -311,6 +318,9 @@ WebContentsAdapterPrivate::WebContentsAdapterPrivate() , adapterClient(0) , nextRequestId(CallbackDirectory::ReservedCallbackIdsEnd) , lastFindRequestId(0) + , currentDropData(nullptr) + , currentDropAction(Qt::IgnoreAction) + , inDragUpdateLoop(false) { } @@ -398,7 +408,7 @@ void WebContentsAdapter::initialize(WebContentsAdapterClient *adapterClient) content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); Q_ASSERT(rvh); if (!rvh->IsRenderViewLive()) - static_cast<content::WebContentsImpl*>(d->webContents.get())->CreateRenderViewForRenderManager(rvh, MSG_ROUTING_NONE, MSG_ROUTING_NONE, content::FrameReplicationState(), true); + static_cast<content::WebContentsImpl*>(d->webContents.get())->CreateRenderViewForRenderManager(rvh, MSG_ROUTING_NONE, MSG_ROUTING_NONE, content::FrameReplicationState()); } void WebContentsAdapter::reattachRWHV() @@ -489,6 +499,12 @@ void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeT d->webContents->Focus(); } +void WebContentsAdapter::save() +{ + Q_D(WebContentsAdapter); + d->webContents->OnSavePage(); +} + QUrl WebContentsAdapter::activeUrl() const { Q_D(const WebContentsAdapter); @@ -582,6 +598,12 @@ void WebContentsAdapter::requestClose() d->webContents->DispatchBeforeUnload(false); } +void WebContentsAdapter::unselect() +{ + Q_D(const WebContentsAdapter); + d->webContents->Unselect(); +} + void WebContentsAdapter::navigateToIndex(int offset) { Q_D(WebContentsAdapter); @@ -698,21 +720,30 @@ QAccessibleInterface *WebContentsAdapter::browserAccessible() } #endif // QT_NO_ACCESSIBILITY -void WebContentsAdapter::runJavaScript(const QString &javaScript) +void WebContentsAdapter::runJavaScript(const QString &javaScript, quint32 worldId) { Q_D(WebContentsAdapter); content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); Q_ASSERT(rvh); - rvh->GetMainFrame()->ExecuteJavaScript(toString16(javaScript)); + if (worldId == 0) { + rvh->GetMainFrame()->ExecuteJavaScript(toString16(javaScript)); + return; + } + + content::RenderFrameHost::JavaScriptResultCallback callback = base::Bind(&callbackOnEvaluateJS, d->adapterClient, CallbackDirectory::NoCallbackId); + rvh->GetMainFrame()->ExecuteJavaScriptInIsolatedWorld(toString16(javaScript), callback, worldId); } -quint64 WebContentsAdapter::runJavaScriptCallbackResult(const QString &javaScript) +quint64 WebContentsAdapter::runJavaScriptCallbackResult(const QString &javaScript, quint32 worldId) { Q_D(WebContentsAdapter); content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); Q_ASSERT(rvh); content::RenderFrameHost::JavaScriptResultCallback callback = base::Bind(&callbackOnEvaluateJS, d->adapterClient, d->nextRequestId); - rvh->GetMainFrame()->ExecuteJavaScript(toString16(javaScript), callback); + if (worldId == 0) + rvh->GetMainFrame()->ExecuteJavaScript(toString16(javaScript), callback); + else + rvh->GetMainFrame()->ExecuteJavaScriptInIsolatedWorld(toString16(javaScript), callback, worldId); return d->nextRequestId++; } @@ -782,6 +813,24 @@ void WebContentsAdapter::download(const QUrl &url, const QString &suggestedFileN dlm->DownloadUrl(params.Pass()); } +bool WebContentsAdapter::isAudioMuted() const +{ + const Q_D(WebContentsAdapter); + return d->webContents->IsAudioMuted(); +} + +void WebContentsAdapter::setAudioMuted(bool muted) +{ + Q_D(WebContentsAdapter); + d->webContents->SetAudioMuted(muted); +} + +bool WebContentsAdapter::wasRecentlyAudible() +{ + Q_D(WebContentsAdapter); + return d->webContents->WasRecentlyAudible(); +} + void WebContentsAdapter::copyImageAt(const QPoint &location) { Q_D(WebContentsAdapter); @@ -841,6 +890,22 @@ void WebContentsAdapter::wasHidden() d->webContents->WasHidden(); } +QPointF WebContentsAdapter::lastScrollOffset() const +{ + Q_D(const WebContentsAdapter); + if (content::RenderWidgetHostView *rwhv = d->webContents->GetRenderWidgetHostView()) + return toQt(rwhv->GetLastScrollOffset()); + return QPointF(); +} + +QSizeF WebContentsAdapter::lastContentsSize() const +{ + Q_D(const WebContentsAdapter); + if (RenderWidgetHostViewQt *rwhv = static_cast<RenderWidgetHostViewQt *>(d->webContents->GetRenderWidgetHostView())) + return toQt(rwhv->lastContentsSize()); + return QSizeF(); +} + void WebContentsAdapter::grantMediaAccessPermission(const QUrl &securityOrigin, WebContentsAdapterClient::MediaRequestFlags flags) { Q_D(WebContentsAdapter); @@ -914,6 +979,154 @@ void WebContentsAdapter::setWebChannel(QWebChannel *channel) channel->connectTo(d->webChannelTransport.get()); } +static QMimeData *mimeDataFromDropData(const content::DropData &dropData) +{ + QMimeData *mimeData = new QMimeData(); + if (!dropData.text.is_null()) { + mimeData->setText(toQt(dropData.text.string())); + return mimeData; + } + if (!dropData.html.is_null()) { + mimeData->setHtml(toQt(dropData.html.string())); + return mimeData; + } + if (dropData.url.is_valid()) { + mimeData->setUrls(QList<QUrl>() << toQt(dropData.url)); + return mimeData; + } + return mimeData; +} + +void WebContentsAdapter::startDragging(QObject *dragSource, const content::DropData &dropData, + Qt::DropActions allowedActions, const QPixmap &pixmap, + const QPoint &offset) +{ + Q_D(WebContentsAdapter); + + if (d->currentDropData) + return; + + // Clear certain fields of the drop data to not run into DCHECKs + // of DropDataToWebDragData in render_view_impl.cc. + content::DropData fixedDropData = dropData; + fixedDropData.download_metadata.clear(); + fixedDropData.file_contents.clear(); + fixedDropData.file_description_filename.clear(); + + d->currentDropAction = Qt::IgnoreAction; + d->currentDropData = &fixedDropData; + QDrag *drag = new QDrag(dragSource); // will be deleted by Qt's DnD implementation + drag->setMimeData(mimeDataFromDropData(fixedDropData)); + if (!pixmap.isNull()) { + drag->setPixmap(pixmap); + drag->setHotSpot(offset); + } + + { + base::MessageLoop::ScopedNestableTaskAllower allow(base::MessageLoop::current()); + drag->exec(allowedActions); + } + + content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); + rvh->DragSourceSystemDragEnded(); + d->currentDropData = nullptr; +} + +static blink::WebDragOperationsMask toWeb(const Qt::DropActions action) +{ + int result = blink::WebDragOperationNone; + if (action & Qt::CopyAction) + result |= blink::WebDragOperationCopy; + if (action & Qt::LinkAction) + result |= blink::WebDragOperationLink; + if (action & Qt::MoveAction) + result |= blink::WebDragOperationMove; + return static_cast<blink::WebDragOperationsMask>(result); +} + +static void fillDropDataFromMimeData(content::DropData *dropData, const QMimeData *mimeData) +{ + if (mimeData->hasText()) + dropData->text = toNullableString16(mimeData->text()); + if (mimeData->hasHtml()) + dropData->html = toNullableString16(mimeData->html()); + Q_FOREACH (const QUrl &url, mimeData->urls()) { + if (url.isLocalFile()) { + ui::FileInfo uifi; + uifi.path = toFilePath(url.toLocalFile()); + dropData->filenames.push_back(uifi); + } + } +} + +void WebContentsAdapter::enterDrag(QDragEnterEvent *e, const QPoint &screenPos) +{ + Q_D(WebContentsAdapter); + + scoped_ptr<content::DropData> ownedDropData; + const content::DropData *rvhDropData = d->currentDropData; + if (!rvhDropData) { + // The drag originated outside the WebEngineView. + ownedDropData.reset(new content::DropData); + fillDropDataFromMimeData(ownedDropData.get(), e->mimeData()); + rvhDropData = ownedDropData.get(); + } + + content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); + rvh->DragTargetDragEnter(*rvhDropData, toGfx(e->pos()), toGfx(screenPos), + toWeb(e->possibleActions()), + flagsFromModifiers(e->keyboardModifiers())); +} + +Qt::DropAction WebContentsAdapter::updateDragPosition(QDragMoveEvent *e, const QPoint &screenPos) +{ + Q_D(WebContentsAdapter); + content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); + rvh->DragTargetDragOver(toGfx(e->pos()), toGfx(screenPos), toWeb(e->possibleActions()), + blink::WebInputEvent::LeftButtonDown); + + // Wait until we get notified via RenderViewHostDelegateView::UpdateDragCursor. This calls + // WebContentsAdapter::updateDragAction that will eventually quit the nested loop. + base::RunLoop loop; + d->inDragUpdateLoop = true; + d->dragUpdateLoopQuitClosure = loop.QuitClosure(); + loop.Run(); + + return d->currentDropAction; +} + +void WebContentsAdapter::updateDragAction(Qt::DropAction action) +{ + Q_D(WebContentsAdapter); + d->currentDropAction = action; + finishDragUpdate(); +} + +void WebContentsAdapter::finishDragUpdate() +{ + Q_D(WebContentsAdapter); + if (d->inDragUpdateLoop) { + d->dragUpdateLoopQuitClosure.Run(); + d->inDragUpdateLoop = false; + } +} + +void WebContentsAdapter::endDragging(const QPoint &clientPos, const QPoint &screenPos) +{ + Q_D(WebContentsAdapter); + finishDragUpdate(); + content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); + rvh->DragTargetDrop(toGfx(clientPos), toGfx(screenPos), 0); +} + +void WebContentsAdapter::leaveDrag() +{ + Q_D(WebContentsAdapter); + finishDragUpdate(); + content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); + rvh->DragTargetDragLeave(); +} + WebContentsAdapterClient::RenderProcessTerminationStatus WebContentsAdapterClient::renderProcessExitStatus(int terminationStatus) { auto status = WebContentsAdapterClient::RenderProcessTerminationStatus(-1); diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h index ce033bdb4..90e035da1 100644 --- a/src/core/web_contents_adapter.h +++ b/src/core/web_contents_adapter.h @@ -52,6 +52,8 @@ struct WebPreferences; QT_BEGIN_NAMESPACE class QAccessibleInterface; +class QDragEnterEvent; +class QDragMoveEvent; class QWebChannel; QT_END_NAMESPACE @@ -77,6 +79,7 @@ public: void reloadAndBypassCache(); void load(const QUrl&); void setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl); + void save(); QUrl activeUrl() const; QUrl requestedUrl() const; QString pageTitle() const; @@ -90,6 +93,7 @@ public: void paste(); void pasteAndMatchStyle(); void selectAll(); + void unselect(); void navigateToIndex(int); void navigateToOffset(int); @@ -104,14 +108,17 @@ public: void serializeNavigationHistory(QDataStream &output); void setZoomFactor(qreal); qreal currentZoomFactor() const; - void runJavaScript(const QString &javaScript); - quint64 runJavaScriptCallbackResult(const QString &javaScript); + void runJavaScript(const QString &javaScript, quint32 worldId); + quint64 runJavaScriptCallbackResult(const QString &javaScript, quint32 worldId); quint64 fetchDocumentMarkup(); quint64 fetchDocumentInnerText(); quint64 findText(const QString &subString, bool caseSensitively, bool findBackward); void stopFinding(); void updateWebPreferences(const content::WebPreferences &webPreferences); void download(const QUrl &url, const QString &suggestedFileName); + bool isAudioMuted() const; + void setAudioMuted(bool mute); + bool wasRecentlyAudible(); // Must match blink::WebMediaPlayerAction::Type. enum MediaPlayerAction { @@ -145,6 +152,18 @@ public: QWebChannel *webChannel() const; void setWebChannel(QWebChannel *); + QPointF lastScrollOffset() const; + QSizeF lastContentsSize() const; + + void startDragging(QObject *dragSource, const content::DropData &dropData, + Qt::DropActions allowedActions, const QPixmap &pixmap, const QPoint &offset); + void enterDrag(QDragEnterEvent *e, const QPoint &screenPos); + Qt::DropAction updateDragPosition(QDragMoveEvent *e, const QPoint &screenPos); + void updateDragAction(Qt::DropAction action); + void finishDragUpdate(); + void endDragging(const QPoint &clientPos, const QPoint &screenPos); + void leaveDrag(); + // meant to be used within WebEngineCore only content::WebContents *webContents() const; diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h index 117e21e25..d3eae2b00 100644 --- a/src/core/web_contents_adapter_client.h +++ b/src/core/web_contents_adapter_client.h @@ -50,10 +50,15 @@ QT_FORWARD_DECLARE_CLASS(QKeyEvent) QT_FORWARD_DECLARE_CLASS(QVariant) QT_FORWARD_DECLARE_CLASS(CertificateErrorController) +namespace content { +struct DropData; +} + namespace QtWebEngineCore { class AuthenticationDialogController; class BrowserContextAdapter; +class ColorChooserController; class FilePickerController; class JavaScriptDialogController; class RenderWidgetHostViewQt; @@ -197,6 +202,7 @@ public: virtual void loadProgressChanged(int progress) = 0; virtual void didUpdateTargetURL(const QUrl&) = 0; virtual void selectionChanged() = 0; + virtual void wasRecentlyAudibleChanged(bool wasRecentlyAudible) = 0; virtual QRectF viewportRect() const = 0; virtual qreal dpiScale() const = 0; virtual QColor backgroundColor() const = 0; @@ -216,6 +222,7 @@ public: virtual bool isFullScreenMode() const = 0; virtual void javascriptDialog(QSharedPointer<JavaScriptDialogController>) = 0; virtual void runFileChooser(FilePickerController *controller) = 0; + virtual void showColorDialog(QSharedPointer<ColorChooserController>) = 0; virtual void didRunJavaScript(quint64 requestId, const QVariant& result) = 0; virtual void didFetchDocumentMarkup(quint64 requestId, const QString& result) = 0; virtual void didFetchDocumentInnerText(quint64 requestId, const QString& result) = 0; @@ -239,9 +246,13 @@ public: virtual void renderProcessTerminated(RenderProcessTerminationStatus terminationStatus, int exitCode) = 0; virtual void allowCertificateError(const QSharedPointer<CertificateErrorController> &errorController) = 0; + virtual void updateScrollPosition(const QPointF &position) = 0; + virtual void updateContentsSize(const QSizeF &size) = 0; + virtual void startDragging(const content::DropData &dropData, Qt::DropActions allowedActions, + const QPixmap &pixmap, const QPoint &offset) = 0; virtual 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 22f295b32..63f075bce 100644 --- a/src/core/web_contents_adapter_p.h +++ b/src/core/web_contents_adapter_p.h @@ -50,6 +50,7 @@ #include "web_contents_adapter.h" +#include <base/callback.h> #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" @@ -59,6 +60,10 @@ QT_FORWARD_DECLARE_CLASS(QWebChannel) class WebEngineContext; +namespace content { +struct DropData; +} + namespace QtWebEngineCore { class BrowserContextAdapter; @@ -67,6 +72,7 @@ class UserScriptControllerHost; class WebChannelIPCTransportHost; class WebContentsAdapterClient; class WebContentsDelegateQt; +class WebEngineContext; class WebContentsAdapterPrivate { public: @@ -82,6 +88,10 @@ public: WebContentsAdapterClient *adapterClient; quint64 nextRequestId; int lastFindRequestId; + const content::DropData *currentDropData; + Qt::DropAction currentDropAction; + bool inDragUpdateLoop; + base::Closure dragUpdateLoopQuitClosure; }; } // namespace QtWebEngineCore diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index 59fa0a9a8..c8e8da713 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -41,6 +41,8 @@ #include "web_contents_delegate_qt.h" #include "browser_context_adapter.h" +#include "color_chooser_qt.h" +#include "color_chooser_controller.h" #include "file_picker_controller.h" #include "media_capture_devices_dispatcher.h" #include "network_delegate_qt.h" @@ -120,6 +122,15 @@ void WebContentsDelegateQt::NavigationStateChanged(content::WebContents* source, m_viewClient->urlChanged(toQt(source->GetVisibleURL())); if (changed_flags & content::INVALIDATE_TYPE_TITLE) m_viewClient->titleChanged(toQt(source->GetTitle())); + + // NavigationStateChanged gets called with INVALIDATE_TYPE_TAB by AudioStateProvider::Notify, + // whenever an audio sound gets played or stopped, this is the only way to actually figure out + // if there was a recently played audio sound. + // Make sure to only emit the signal when loading isn't in progress, because it causes multiple + // false signals to be emitted. + if ((changed_flags & content::INVALIDATE_TYPE_TAB) && !(changed_flags & content::INVALIDATE_TYPE_LOAD)) { + m_viewClient->wasRecentlyAudibleChanged(source->WasRecentlyAudible()); + } } void WebContentsDelegateQt::AddNewContents(content::WebContents* source, content::WebContents* new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture, bool* was_blocked) @@ -241,6 +252,14 @@ void WebContentsDelegateQt::DidUpdateFaviconURL(const std::vector<content::Favic } } +content::ColorChooser *WebContentsDelegateQt::OpenColorChooser(content::WebContents *source, SkColor color, const std::vector<content::ColorSuggestion> &suggestion) +{ + Q_UNUSED(suggestion); + ColorChooserQt *colorChooser = new ColorChooserQt(source, toQt(color)); + m_viewClient->showColorDialog(colorChooser->controller()); + + return colorChooser; +} content::JavaScriptDialogManager *WebContentsDelegateQt::GetJavaScriptDialogManager(content::WebContents *) { return JavaScriptDialogManagerQt::GetInstance(); diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h index d3075cfbf..51b290d5a 100644 --- a/src/core/web_contents_delegate_qt.h +++ b/src/core/web_contents_delegate_qt.h @@ -40,9 +40,11 @@ #include "content/public/browser/web_contents_delegate.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/common/permission_status.mojom.h" +#include "third_party/skia/include/core/SkColor.h" #include "base/callback.h" +#include "color_chooser_controller.h" #include "javascript_dialog_manager_qt.h" #include <QtCore/qvector.h> #include <QtCore/qcompilerdetection.h> @@ -51,11 +53,13 @@ QT_FORWARD_DECLARE_CLASS(CertificateErrorController) namespace content { class BrowserContext; + class ColorChooser; class SiteInstance; class RenderViewHost; class JavaScriptDialogManager; class WebContents; struct WebPreferences; + struct ColorSuggestion; } namespace QtWebEngineCore { @@ -79,6 +83,7 @@ public: virtual void CloseContents(content::WebContents *source) Q_DECL_OVERRIDE; virtual void LoadProgressChanged(content::WebContents* source, double progress) Q_DECL_OVERRIDE; virtual void HandleKeyboardEvent(content::WebContents *source, const content::NativeWebKeyboardEvent &event) Q_DECL_OVERRIDE; + virtual content::ColorChooser *OpenColorChooser(content::WebContents *source, SkColor color, const std::vector<content::ColorSuggestion> &suggestion) Q_DECL_OVERRIDE; virtual content::JavaScriptDialogManager *GetJavaScriptDialogManager(content::WebContents *source) Q_DECL_OVERRIDE; virtual void EnterFullscreenModeForTab(content::WebContents* web_contents, const GURL& origin) Q_DECL_OVERRIDE; virtual void ExitFullscreenModeForTab(content::WebContents*) Q_DECL_OVERRIDE; diff --git a/src/core/web_contents_view_qt.cpp b/src/core/web_contents_view_qt.cpp index 67addacd5..153966aea 100644 --- a/src/core/web_contents_view_qt.cpp +++ b/src/core/web_contents_view_qt.cpp @@ -40,10 +40,14 @@ #include "content_browser_client_qt.h" #include "render_widget_host_view_qt_delegate.h" #include "type_conversion.h" +#include "web_contents_adapter.h" #include "web_engine_context.h" #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/public/common/context_menu_params.h" +#include <ui/gfx/image/image_skia.h> + +#include <QtGui/qpixmap.h> namespace QtWebEngineCore { @@ -164,15 +168,51 @@ void WebContentsViewQt::ShowContextMenu(content::RenderFrameHost *, const conten m_client->contextMenuRequested(contextMenuData); } -void WebContentsViewQt::StartDragging(const content::DropData& drop_data, blink::WebDragOperationsMask allowed_ops, const gfx::ImageSkia& image, const gfx::Vector2d& image_offset, const content::DragEventSourceInfo& event_info) +Qt::DropActions toQtDropActions(blink::WebDragOperationsMask ops) +{ + Qt::DropActions result; + if (ops & blink::WebDragOperationCopy) + result |= Qt::CopyAction; + if (ops & blink::WebDragOperationLink) + result |= Qt::LinkAction; + if (ops & blink::WebDragOperationMove || ops & blink::WebDragOperationDelete) + result |= Qt::MoveAction; + return result; +} + +Qt::DropAction toQt(blink::WebDragOperation op) +{ + if (op == blink::WebDragOperationCopy) + return Qt::CopyAction; + if (op == blink::WebDragOperationLink) + return Qt::LinkAction; + if (op == blink::WebDragOperationMove || op == blink::WebDragOperationDelete) + return Qt::MoveAction; + return Qt::IgnoreAction; +} + +void WebContentsViewQt::StartDragging(const content::DropData &drop_data, + blink::WebDragOperationsMask allowed_ops, + const gfx::ImageSkia &image, + const gfx::Vector2d &image_offset, + const content::DragEventSourceInfo &event_info) +{ + Q_UNUSED(event_info); + + QPixmap pixmap; + QPoint hotspot; + pixmap = QPixmap::fromImage(toQImage(image.GetRepresentation(m_client->dpiScale()))); + if (!pixmap.isNull()) { + hotspot.setX(image_offset.x()); + hotspot.setY(image_offset.y()); + } + + m_client->startDragging(drop_data, toQtDropActions(allowed_ops), pixmap, hotspot); +} + +void WebContentsViewQt::UpdateDragCursor(blink::WebDragOperation dragOperation) { - Q_UNUSED(&drop_data); - Q_UNUSED(allowed_ops); - Q_UNUSED(&image); - Q_UNUSED(&image_offset); - Q_UNUSED(&event_info); - // Tell the renderer to cancel the drag, see StartDragging's declaration in render_view_host_delegate_view.h for info. - m_webContents->SystemDragEnded(); + m_client->webContentsAdapter()->updateDragAction(toQt(dragOperation)); } void WebContentsViewQt::TakeFocus(bool reverse) diff --git a/src/core/web_contents_view_qt.h b/src/core/web_contents_view_qt.h index cbbca2371..084fa615d 100644 --- a/src/core/web_contents_view_qt.h +++ b/src/core/web_contents_view_qt.h @@ -104,7 +104,11 @@ public: virtual gfx::Rect GetViewBounds() const Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED return gfx::Rect(); } - virtual void StartDragging(const content::DropData& drop_data, blink::WebDragOperationsMask allowed_ops, const gfx::ImageSkia& image, const gfx::Vector2d& image_offset, const content::DragEventSourceInfo& event_info) Q_DECL_OVERRIDE; + void StartDragging(const content::DropData &drop_data, blink::WebDragOperationsMask allowed_ops, + const gfx::ImageSkia &image, const gfx::Vector2d &image_offset, + const content::DragEventSourceInfo &event_info) Q_DECL_OVERRIDE; + + void UpdateDragCursor(blink::WebDragOperation dragOperation) Q_DECL_OVERRIDE; virtual void ShowContextMenu(content::RenderFrameHost *, const content::ContextMenuParams ¶ms) Q_DECL_OVERRIDE; diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 9c8a6c757..dabee9179 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -52,6 +52,7 @@ #include "content/public/app/content_main.h" #include "content/public/app/content_main_runner.h" #include "content/public/browser/browser_main_runner.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/common/content_paths.h" #include "content/public/common/content_switches.h" #include "content/public/common/main_function_params.h" @@ -91,7 +92,7 @@ QT_END_NAMESPACE namespace { -scoped_refptr<WebEngineContext> sContext; +scoped_refptr<QtWebEngineCore::WebEngineContext> sContext; void destroyContext() { @@ -144,6 +145,8 @@ bool usingQtQuick2DRenderer() } // namespace +namespace QtWebEngineCore { + void WebEngineContext::destroyBrowserContext() { m_defaultBrowserContext = 0; @@ -212,6 +215,9 @@ WebEngineContext::WebEngineContext() useEmbeddedSwitches = !args.removeAll("--disable-embedded-switches"); #endif + // Allow us to inject javascript like any webview toolkit. + content::RenderFrameHost::AllowInjectingJavaScriptForAndroidWebView(); + QVector<const char*> argv(args.size()); for (int i = 0; i < args.size(); ++i) argv[i] = args[i].constData(); @@ -220,9 +226,12 @@ WebEngineContext::WebEngineContext() base::CommandLine* parsedCommandLine = base::CommandLine::ForCurrentProcess(); parsedCommandLine->AppendSwitchPath(switches::kBrowserSubprocessPath, WebEngineLibraryInfo::getPath(content::CHILD_PROCESS_EXE)); parsedCommandLine->AppendSwitch(switches::kNoSandbox); - parsedCommandLine->AppendSwitch(switches::kEnableDelegatedRenderer); parsedCommandLine->AppendSwitch(switches::kEnableThreadedCompositing); parsedCommandLine->AppendSwitch(switches::kInProcessGPU); + // These are currently only default on OS X, and we don't support them: + parsedCommandLine->AppendSwitch(switches::kDisableZeroCopy); + parsedCommandLine->AppendSwitch(switches::kDisableNativeGpuMemoryBuffers); + parsedCommandLine->AppendSwitch(switches::kDisableGpuMemoryBufferVideoFrames); if (useEmbeddedSwitches) { // Inspired by the Android port's default switches @@ -276,3 +285,5 @@ WebEngineContext::WebEngineContext() // first gets referenced on the IO thread. MediaCaptureDevicesDispatcher::GetInstance(); } + +} // namespace diff --git a/src/core/web_engine_context.h b/src/core/web_engine_context.h index 8f034f18f..6c6198b90 100644 --- a/src/core/web_engine_context.h +++ b/src/core/web_engine_context.h @@ -62,7 +62,6 @@ namespace QtWebEngineCore { class BrowserContextAdapter; class ContentMainDelegateQt; class SurfaceFactoryQt; -} // namespace class WebEngineContext : public base::RefCounted<WebEngineContext> { public: @@ -80,12 +79,14 @@ private: ~WebEngineContext(); scoped_ptr<base::RunLoop> m_runLoop; - scoped_ptr<QtWebEngineCore::ContentMainDelegateQt> m_mainDelegate; + scoped_ptr<ContentMainDelegateQt> m_mainDelegate; scoped_ptr<content::ContentMainRunner> m_contentRunner; scoped_ptr<content::BrowserMainRunner> m_browserRunner; QObject* m_globalQObject; - QExplicitlySharedDataPointer<QtWebEngineCore::BrowserContextAdapter> m_defaultBrowserContext; + QExplicitlySharedDataPointer<BrowserContextAdapter> m_defaultBrowserContext; scoped_ptr<devtools_http_handler::DevToolsHttpHandler> m_devtools; }; +} // namespace + #endif // WEB_ENGINE_CONTEXT_H diff --git a/src/core/web_engine_settings.cpp b/src/core/web_engine_settings.cpp index ff67ed6a6..539caed5f 100644 --- a/src/core/web_engine_settings.cpp +++ b/src/core/web_engine_settings.cpp @@ -35,9 +35,14 @@ ****************************************************************************/ #include "web_engine_settings.h" + #include "web_contents_adapter.h" +#include "web_engine_context.h" #include "type_conversion.h" +#include "base/command_line.h" +#include "content/browser/gpu/gpu_process_host.h" +#include "content/public/common/content_switches.h" #include "content/public/common/web_preferences.h" #include <QFont> @@ -46,9 +51,9 @@ namespace QtWebEngineCore { -QHash<WebEngineSettings::Attribute, bool> WebEngineSettings::m_defaultAttributes; -QHash<WebEngineSettings::FontFamily, QString> WebEngineSettings::m_defaultFontFamilies; -QHash<WebEngineSettings::FontSize, int> WebEngineSettings::m_defaultFontSizes; +QHash<WebEngineSettings::Attribute, bool> WebEngineSettings::s_defaultAttributes; +QHash<WebEngineSettings::FontFamily, QString> WebEngineSettings::s_defaultFontFamilies; +QHash<WebEngineSettings::FontSize, int> WebEngineSettings::s_defaultFontSizes; static const int batchTimerTimeout = 0; @@ -128,20 +133,15 @@ void WebEngineSettings::setAttribute(WebEngineSettings::Attribute attr, bool on) bool WebEngineSettings::testAttribute(WebEngineSettings::Attribute attr) const { if (!parentSettings) { - Q_ASSERT(m_attributes.contains(attr)); - return m_attributes.value(attr); + Q_ASSERT(s_defaultAttributes.contains(attr)); + return m_attributes.value(attr, s_defaultAttributes.value(attr)); } return m_attributes.value(attr, parentSettings->testAttribute(attr)); } void WebEngineSettings::resetAttribute(WebEngineSettings::Attribute attr) { - if (!parentSettings) { - Q_ASSERT(m_defaultAttributes.contains(attr)); - m_attributes.insert(attr, m_defaultAttributes.value(attr)); - } else { - m_attributes.remove(attr); - } + m_attributes.remove(attr); scheduleApplyRecursively(); } @@ -154,20 +154,15 @@ void WebEngineSettings::setFontFamily(WebEngineSettings::FontFamily which, const QString WebEngineSettings::fontFamily(WebEngineSettings::FontFamily which) { if (!parentSettings) { - Q_ASSERT(m_fontFamilies.contains(which)); - return m_fontFamilies.value(which); + Q_ASSERT(s_defaultFontFamilies.contains(which)); + return m_fontFamilies.value(which, s_defaultFontFamilies.value(which)); } return m_fontFamilies.value(which, parentSettings->fontFamily(which)); } void WebEngineSettings::resetFontFamily(WebEngineSettings::FontFamily which) { - if (!parentSettings) { - Q_ASSERT(m_defaultFontFamilies.contains(which)); - m_fontFamilies.insert(which, m_defaultFontFamilies.value(which)); - } else { - m_fontFamilies.remove(which); - } + m_fontFamilies.remove(which); scheduleApplyRecursively(); } @@ -180,20 +175,15 @@ void WebEngineSettings::setFontSize(WebEngineSettings::FontSize type, int size) int WebEngineSettings::fontSize(WebEngineSettings::FontSize type) const { if (!parentSettings) { - Q_ASSERT(m_fontSizes.contains(type)); - return m_fontSizes.value(type); + Q_ASSERT(s_defaultFontSizes.contains(type)); + return m_fontSizes.value(type, s_defaultFontSizes.value(type)); } return m_fontSizes.value(type, parentSettings->fontSize(type)); } void WebEngineSettings::resetFontSize(WebEngineSettings::FontSize type) { - if (!parentSettings) { - Q_ASSERT(m_defaultFontSizes.contains(type)); - m_fontSizes.insert(type, m_defaultFontSizes.value(type)); - } else { - m_fontSizes.remove(type); - } + m_fontSizes.remove(type); scheduleApplyRecursively(); } @@ -212,54 +202,68 @@ QString WebEngineSettings::defaultTextEncoding() const void WebEngineSettings::initDefaults(bool offTheRecord) { - if (m_defaultAttributes.isEmpty()) { + if (s_defaultAttributes.isEmpty()) { // Initialize the default settings. - m_defaultAttributes.insert(AutoLoadImages, true); - m_defaultAttributes.insert(JavascriptEnabled, true); - m_defaultAttributes.insert(JavascriptCanOpenWindows, true); - m_defaultAttributes.insert(JavascriptCanAccessClipboard, false); - m_defaultAttributes.insert(LinksIncludedInFocusChain, true); - m_defaultAttributes.insert(LocalStorageEnabled, !offTheRecord); - m_defaultAttributes.insert(LocalContentCanAccessRemoteUrls, false); - m_defaultAttributes.insert(XSSAuditingEnabled, false); - m_defaultAttributes.insert(SpatialNavigationEnabled, false); - m_defaultAttributes.insert(LocalContentCanAccessFileUrls, true); - m_defaultAttributes.insert(HyperlinkAuditingEnabled, false); - m_defaultAttributes.insert(ScrollAnimatorEnabled, false); - m_defaultAttributes.insert(ErrorPageEnabled, true); - m_defaultAttributes.insert(PluginsEnabled, false); - m_defaultAttributes.insert(FullScreenSupportEnabled, false); + s_defaultAttributes.insert(AutoLoadImages, true); + s_defaultAttributes.insert(JavascriptEnabled, true); + s_defaultAttributes.insert(JavascriptCanOpenWindows, true); + s_defaultAttributes.insert(JavascriptCanAccessClipboard, false); + s_defaultAttributes.insert(LinksIncludedInFocusChain, true); + s_defaultAttributes.insert(LocalStorageEnabled, true); + s_defaultAttributes.insert(LocalContentCanAccessRemoteUrls, false); + s_defaultAttributes.insert(XSSAuditingEnabled, false); + s_defaultAttributes.insert(SpatialNavigationEnabled, false); + s_defaultAttributes.insert(LocalContentCanAccessFileUrls, true); + s_defaultAttributes.insert(HyperlinkAuditingEnabled, false); + s_defaultAttributes.insert(ErrorPageEnabled, true); + 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(); + base::CommandLine* commandLine = base::CommandLine::ForCurrentProcess(); + bool smoothScrolling = commandLine->HasSwitch(switches::kEnableSmoothScrolling); + bool webGL = content::GpuProcessHost::gpu_enabled() && + !commandLine->HasSwitch(switches::kDisable3DAPIs) && + !commandLine->HasSwitch(switches::kDisableExperimentalWebGL); + bool accelerated2dCanvas = content::GpuProcessHost::gpu_enabled() && + !commandLine->HasSwitch(switches::kDisableAccelerated2dCanvas); + s_defaultAttributes.insert(ScrollAnimatorEnabled, smoothScrolling); + s_defaultAttributes.insert(WebGLEnabled, webGL); + s_defaultAttributes.insert(Accelerated2dCanvasEnabled, accelerated2dCanvas); } - m_attributes = m_defaultAttributes; + if (offTheRecord) + m_attributes.insert(LocalStorageEnabled, false); - if (m_defaultFontFamilies.isEmpty()) { + if (s_defaultFontFamilies.isEmpty()) { // Default fonts QFont defaultFont; defaultFont.setStyleHint(QFont::Serif); - m_defaultFontFamilies.insert(StandardFont, defaultFont.defaultFamily()); - m_defaultFontFamilies.insert(SerifFont, defaultFont.defaultFamily()); + s_defaultFontFamilies.insert(StandardFont, defaultFont.defaultFamily()); + s_defaultFontFamilies.insert(SerifFont, defaultFont.defaultFamily()); + s_defaultFontFamilies.insert(PictographFont, defaultFont.defaultFamily()); defaultFont.setStyleHint(QFont::Fantasy); - m_defaultFontFamilies.insert(FantasyFont, defaultFont.defaultFamily()); + s_defaultFontFamilies.insert(FantasyFont, defaultFont.defaultFamily()); defaultFont.setStyleHint(QFont::Cursive); - m_defaultFontFamilies.insert(CursiveFont, defaultFont.defaultFamily()); + s_defaultFontFamilies.insert(CursiveFont, defaultFont.defaultFamily()); defaultFont.setStyleHint(QFont::SansSerif); - m_defaultFontFamilies.insert(SansSerifFont, defaultFont.defaultFamily()); + s_defaultFontFamilies.insert(SansSerifFont, defaultFont.defaultFamily()); defaultFont.setStyleHint(QFont::Monospace); - m_defaultFontFamilies.insert(FixedFont, defaultFont.defaultFamily()); + s_defaultFontFamilies.insert(FixedFont, defaultFont.defaultFamily()); } - m_fontFamilies = m_defaultFontFamilies; - if (m_defaultFontSizes.isEmpty()) { - m_defaultFontSizes.insert(MinimumFontSize, 0); - m_defaultFontSizes.insert(MinimumLogicalFontSize, 6); - m_defaultFontSizes.insert(DefaultFixedFontSize, 13); - m_defaultFontSizes.insert(DefaultFontSize, 16); + if (s_defaultFontSizes.isEmpty()) { + s_defaultFontSizes.insert(MinimumFontSize, 0); + s_defaultFontSizes.insert(MinimumLogicalFontSize, 6); + s_defaultFontSizes.insert(DefaultFixedFontSize, 13); + s_defaultFontSizes.insert(DefaultFontSize, 16); } - m_fontSizes = m_defaultFontSizes; m_defaultEncoding = QStringLiteral("ISO-8859-1"); } @@ -284,7 +288,6 @@ void WebEngineSettings::doApply() void WebEngineSettings::applySettingsToWebPreferences(content::WebPreferences *prefs) { // Override for now - prefs->java_enabled = false; prefs->touch_enabled = isTouchScreenAvailable(); // Attributes mapping. @@ -303,6 +306,9 @@ void WebEngineSettings::applySettingsToWebPreferences(content::WebPreferences *p prefs->enable_error_page = testAttribute(ErrorPageEnabled); 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. prefs->standard_font_family_map[content::kCommonScript] = toString16(fontFamily(StandardFont)); @@ -311,8 +317,7 @@ void WebEngineSettings::applySettingsToWebPreferences(content::WebPreferences *p prefs->sans_serif_font_family_map[content::kCommonScript] = toString16(fontFamily(SansSerifFont)); prefs->cursive_font_family_map[content::kCommonScript] = toString16(fontFamily(CursiveFont)); prefs->fantasy_font_family_map[content::kCommonScript] = toString16(fontFamily(FantasyFont)); - // FIXME: add pictograph? - // prefs.pictograph_font_family_map[content::kCommonScript] = toString16(fontFamily()); + prefs->pictograph_font_family_map[content::kCommonScript] = toString16(fontFamily(PictographFont)); prefs->default_font_size = fontSize(DefaultFontSize); prefs->default_fixed_font_size = fontSize(DefaultFixedFontSize); prefs->minimum_font_size = fontSize(MinimumFontSize); diff --git a/src/core/web_engine_settings.h b/src/core/web_engine_settings.h index 3d3d734d0..9673b9558 100644 --- a/src/core/web_engine_settings.h +++ b/src/core/web_engine_settings.h @@ -73,6 +73,10 @@ public: ErrorPageEnabled, PluginsEnabled, FullScreenSupportEnabled, + ScreenCaptureEnabled, + WebGLEnabled, + WebAudioEnabled, + Accelerated2dCanvasEnabled }; // Must match the values from the public API in qwebenginesettings.h. @@ -82,7 +86,8 @@ public: SerifFont, SansSerifFont, CursiveFont, - FantasyFont + FantasyFont, + PictographFont }; // Must match the values from the public API in qwebenginesettings.h. @@ -136,9 +141,9 @@ private: WebEngineSettings *parentSettings; QSet<WebEngineSettings *> childSettings; - static QHash<Attribute, bool> m_defaultAttributes; - static QHash<FontFamily, QString> m_defaultFontFamilies; - static QHash<FontSize, int> m_defaultFontSizes; + static QHash<Attribute, bool> s_defaultAttributes; + static QHash<FontFamily, QString> s_defaultFontFamilies; + static QHash<FontSize, int> s_defaultFontSizes; friend class BatchTimer; friend class WebContentsAdapter; diff --git a/src/webengine/api/qquickwebenginedownloaditem.cpp b/src/webengine/api/qquickwebenginedownloaditem.cpp index 2c1ec1ce9..0dbbb05fd 100644 --- a/src/webengine/api/qquickwebenginedownloaditem.cpp +++ b/src/webengine/api/qquickwebenginedownloaditem.cpp @@ -62,6 +62,7 @@ QQuickWebEngineDownloadItemPrivate::QQuickWebEngineDownloadItemPrivate(QQuickWeb : profile(p) , downloadId(-1) , downloadState(QQuickWebEngineDownloadItem::DownloadCancelled) + , savePageFormat(QQuickWebEngineDownloadItem::UnknownSaveFormat) , totalBytes(-1) , receivedBytes(0) { @@ -261,6 +262,34 @@ void QQuickWebEngineDownloadItem::setPath(QString path) } } +/*! + \qmlproperty enumeration WebEngineDownloadItem::savePageFormat + + Describes the format that is used to save a web page. + + \value UnknownSaveFormat This is not a request for downloading a complete web page. + \value SingleHtmlSaveFormat The page is saved as a single HTML page. Resources such as images + are not saved. + \value CompleteHtmlSaveFormat The page is saved as a complete HTML page, for example a directory + containing the single HTML page and the resources. + \value MimeHtmlSaveFormat The page is saved as a complete web page in the MIME HTML format. +*/ + +QQuickWebEngineDownloadItem::SavePageFormat QQuickWebEngineDownloadItem::savePageFormat() const +{ + Q_D(const QQuickWebEngineDownloadItem); + return d->savePageFormat; +} + +void QQuickWebEngineDownloadItem::setSavePageFormat(QQuickWebEngineDownloadItem::SavePageFormat format) +{ + Q_D(QQuickWebEngineDownloadItem); + if (d->savePageFormat != format) { + d->savePageFormat = format; + Q_EMIT savePageFormatChanged(); + } +} + QQuickWebEngineDownloadItem::QQuickWebEngineDownloadItem(QQuickWebEngineDownloadItemPrivate *p, QObject *parent) : QObject(parent) , d_ptr(p) diff --git a/src/webengine/api/qquickwebenginedownloaditem_p.h b/src/webengine/api/qquickwebenginedownloaditem_p.h index 124cea1a5..46b39fe0a 100644 --- a/src/webengine/api/qquickwebenginedownloaditem_p.h +++ b/src/webengine/api/qquickwebenginedownloaditem_p.h @@ -71,8 +71,17 @@ public: }; Q_ENUM(DownloadState) + enum SavePageFormat { + UnknownSaveFormat = -1, + SingleHtmlSaveFormat, + CompleteHtmlSaveFormat, + MimeHtmlSaveFormat + }; + Q_ENUM(SavePageFormat) + Q_PROPERTY(quint32 id READ id CONSTANT FINAL) Q_PROPERTY(DownloadState state READ state NOTIFY stateChanged) + Q_PROPERTY(SavePageFormat savePageFormat READ savePageFormat WRITE setSavePageFormat NOTIFY savePageFormatChanged) Q_PROPERTY(qint64 totalBytes READ totalBytes NOTIFY totalBytesChanged) Q_PROPERTY(qint64 receivedBytes READ receivedBytes NOTIFY receivedBytesChanged) Q_PROPERTY(QString mimeType READ mimeType NOTIFY mimeTypeChanged REVISION 1) @@ -88,9 +97,12 @@ public: QString mimeType() const; QString path() const; void setPath(QString path); + SavePageFormat savePageFormat() const; + void setSavePageFormat(SavePageFormat format); Q_SIGNALS: void stateChanged(); + void savePageFormatChanged(); void receivedBytesChanged(); void totalBytesChanged(); void mimeTypeChanged(); diff --git a/src/webengine/api/qquickwebenginedownloaditem_p_p.h b/src/webengine/api/qquickwebenginedownloaditem_p_p.h index 8e502c736..a85e4e6c4 100644 --- a/src/webengine/api/qquickwebenginedownloaditem_p_p.h +++ b/src/webengine/api/qquickwebenginedownloaditem_p_p.h @@ -69,6 +69,7 @@ public: quint32 downloadId; QQuickWebEngineDownloadItem::DownloadState downloadState; + QQuickWebEngineDownloadItem::SavePageFormat savePageFormat; qint64 totalBytes; qint64 receivedBytes; QString mimeType; diff --git a/src/webengine/api/qquickwebengineprofile.cpp b/src/webengine/api/qquickwebengineprofile.cpp index 27457729f..523121b6f 100644 --- a/src/webengine/api/qquickwebengineprofile.cpp +++ b/src/webengine/api/qquickwebengineprofile.cpp @@ -45,12 +45,17 @@ #include <QQmlEngine> #include "browser_context_adapter.h" +#include <qtwebenginecoreglobal.h> #include "web_engine_settings.h" using QtWebEngineCore::BrowserContextAdapter; QT_BEGIN_NAMESPACE +ASSERT_ENUMS_MATCH(QQuickWebEngineDownloadItem::UnknownSaveFormat, QtWebEngineCore::BrowserContextAdapterClient::UnknownSavePageFormat) +ASSERT_ENUMS_MATCH(QQuickWebEngineDownloadItem::SingleHtmlSaveFormat, QtWebEngineCore::BrowserContextAdapterClient::SingleHtmlSaveFormat) +ASSERT_ENUMS_MATCH(QQuickWebEngineDownloadItem::CompleteHtmlSaveFormat, QtWebEngineCore::BrowserContextAdapterClient::CompleteHtmlSaveFormat) +ASSERT_ENUMS_MATCH(QQuickWebEngineDownloadItem::MimeHtmlSaveFormat, QtWebEngineCore::BrowserContextAdapterClient::MimeHtmlSaveFormat) /*! \class QQuickWebEngineProfile @@ -157,6 +162,8 @@ void QQuickWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info) itemPrivate->totalBytes = info.totalBytes; itemPrivate->mimeType = info.mimeType; itemPrivate->downloadPath = info.path; + itemPrivate->savePageFormat = static_cast<QQuickWebEngineDownloadItem::SavePageFormat>( + info.savePageFormat); QQuickWebEngineDownloadItem *download = new QQuickWebEngineDownloadItem(itemPrivate, q); @@ -167,6 +174,7 @@ void QQuickWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info) QQuickWebEngineDownloadItem::DownloadState state = download->state(); info.path = download->path(); + info.savePageFormat = itemPrivate->savePageFormat; info.accepted = state != QQuickWebEngineDownloadItem::DownloadCancelled && state != QQuickWebEngineDownloadItem::DownloadRequested; } @@ -589,6 +597,29 @@ QWebEngineCookieStore *QQuickWebEngineProfile::cookieStore() const } /*! + \qmlmethod void WebEngineProfile::clearHttpCache() + \since QtWebEngine 1.3 + + Removes the profile's cache entries. + + \sa WebEngineProfile::cachePath +*/ + +/*! + \since 5.7 + + Removes the profile's cache entries. + + \sa WebEngineProfile::clearHttpCache +*/ +void QQuickWebEngineProfile::clearHttpCache() +{ + Q_D(QQuickWebEngineProfile); + d->browserContext()->clearHttpCache(); +} + + +/*! Registers a request interceptor singleton \a interceptor to intercept URL requests. The profile does not take ownership of the pointer. diff --git a/src/webengine/api/qquickwebengineprofile.h b/src/webengine/api/qquickwebengineprofile.h index 1850f52fa..7905e5d29 100644 --- a/src/webengine/api/qquickwebengineprofile.h +++ b/src/webengine/api/qquickwebengineprofile.h @@ -122,6 +122,8 @@ public: void removeUrlSchemeHandler(QWebEngineUrlSchemeHandler *); void removeAllUrlSchemeHandlers(); + void clearHttpCache(); + static QQuickWebEngineProfile *defaultProfile(); Q_SIGNALS: diff --git a/src/webengine/api/qquickwebenginesettings.cpp b/src/webengine/api/qquickwebenginesettings.cpp index fe421993a..5bbca191d 100644 --- a/src/webengine/api/qquickwebenginesettings.cpp +++ b/src/webengine/api/qquickwebenginesettings.cpp @@ -233,6 +233,59 @@ bool QQuickWebEngineSettings::fullScreenSupportEnabled() const } /*! + \qmlproperty bool WebEngineSettings::screenCaptureEnabled + \since QtWebEngine 1.3 + + Tells the web engine whether screen capture is supported in this application or not. + + Disabled by default. +*/ +bool QQuickWebEngineSettings::screenCaptureEnabled() const +{ + return d_ptr->testAttribute(WebEngineSettings::ScreenCaptureEnabled); +} + +/*! + \qmlproperty bool WebEngineSettings::webGLEnabled + \since QtWebEngine 1.3 + + Enables support for HTML 5 WebGL. + + Enabled by default if available. +*/ +bool QQuickWebEngineSettings::webGLEnabled() const +{ + return d_ptr->testAttribute(WebEngineSettings::WebGLEnabled); +} + +/*! + \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 + + Specifies whether the HTML 5 2D canvas should be a OpenGL framebuffer. + This makes many painting operations faster, but slows down pixel access. + + Enabled by default if available. +*/ +bool QQuickWebEngineSettings::accelerated2dCanvasEnabled() const +{ + return d_ptr->testAttribute(WebEngineSettings::Accelerated2dCanvasEnabled); +} + +/*! \qmlproperty QString WebEngineSettings::defaultTextEncoding Sets the default encoding. The value must be a string describing an encoding such as "utf-8" or @@ -352,6 +405,38 @@ void QQuickWebEngineSettings::setFullScreenSupportEnabled(bool on) Q_EMIT fullScreenSupportEnabledChanged(); } +void QQuickWebEngineSettings::setScreenCaptureEnabled(bool on) +{ + bool wasOn = d_ptr->testAttribute(WebEngineSettings::ScreenCaptureEnabled); + d_ptr->setAttribute(WebEngineSettings::ScreenCaptureEnabled, on); + if (wasOn != on) + Q_EMIT screenCaptureEnabledChanged(); +} + +void QQuickWebEngineSettings::setWebGLEnabled(bool on) +{ + bool wasOn = d_ptr->testAttribute(WebEngineSettings::WebGLEnabled); + d_ptr->setAttribute(WebEngineSettings::WebGLEnabled, on); + if (wasOn != 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); + d_ptr->setAttribute(WebEngineSettings::Accelerated2dCanvasEnabled, on); + if (wasOn != on) + Q_EMIT accelerated2dCanvasEnabledChanged(); +} + void QQuickWebEngineSettings::setDefaultTextEncoding(QString encoding) { const QString oldDefaultTextEncoding = d_ptr->defaultTextEncoding(); diff --git a/src/webengine/api/qquickwebenginesettings_p.h b/src/webengine/api/qquickwebenginesettings_p.h index 030762ed3..d307dec1c 100644 --- a/src/webengine/api/qquickwebenginesettings_p.h +++ b/src/webengine/api/qquickwebenginesettings_p.h @@ -74,6 +74,11 @@ class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineSettings : public QObject { Q_PROPERTY(bool pluginsEnabled READ pluginsEnabled WRITE setPluginsEnabled NOTIFY pluginsEnabledChanged) // FIXME(QTBUG-40043): Mark fullScreenSupportEnabled with REVISION 1 Q_PROPERTY(bool fullScreenSupportEnabled READ fullScreenSupportEnabled WRITE setFullScreenSupportEnabled NOTIFY fullScreenSupportEnabledChanged) + // FIXME: add back REVISION when QTBUG-40043 has been fixed. + 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(QString defaultTextEncoding READ defaultTextEncoding WRITE setDefaultTextEncoding NOTIFY defaultTextEncodingChanged) public: @@ -92,6 +97,10 @@ public: bool errorPageEnabled() const; bool pluginsEnabled() const; bool fullScreenSupportEnabled() const; + bool screenCaptureEnabled() const; + bool webGLEnabled() const; + bool webAudioEnabled() const; + bool accelerated2dCanvasEnabled() const; QString defaultTextEncoding() const; void setAutoLoadImages(bool on); @@ -107,6 +116,10 @@ public: void setErrorPageEnabled(bool on); void setPluginsEnabled(bool on); void setFullScreenSupportEnabled(bool on); + void setScreenCaptureEnabled(bool on); + void setWebGLEnabled(bool on); + void setWebAudioEnabled(bool on); + void setAccelerated2dCanvasEnabled(bool on); void setDefaultTextEncoding(QString encoding); signals: @@ -124,6 +137,11 @@ signals: void pluginsEnabledChanged(); // FIXME(QTBUG-40043): Mark fullScreenSupportEnabledChanged with Q_REVISION(1) void fullScreenSupportEnabledChanged(); + // FIXME: add back Q_REVISION when QTBUG-40043 has been fixed. + void screenCaptureEnabledChanged(); + void webGLEnabledChanged(); + void webAudioEnabledChanged(); + void accelerated2dCanvasEnabledChanged(); void defaultTextEncodingChanged(); private: diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index c6d849387..61a19faa5 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -208,10 +208,21 @@ bool QQuickWebEngineViewPrivate::contextMenuRequested(const WebEngineContextMenu item = new MenuItemHandler(menu); QObject::connect(item, &MenuItemHandler::triggered, q, &QQuickWebEngineView::reload); ui()->addMenuItem(item, QQuickWebEngineView::tr("Reload"), QStringLiteral("view-refresh")); + + if (!data.linkUrl.isValid()) { + item = new MenuItemHandler(menu); + QObject::connect(item, &MenuItemHandler::triggered, [q] { + q->triggerWebAction(QQuickWebEngineView::SavePage); + }); + ui()->addMenuItem(item, QQuickWebEngineView::tr("Save")); + } } else { item = new MenuItemHandler(menu); QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::Copy); }); ui()->addMenuItem(item, QQuickWebEngineView::tr("Copy")); + item = new MenuItemHandler(menu); + QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::Unselect); }); + ui()->addMenuItem(item, QQuickWebEngineView::tr("Unselect")); } if (!contextMenuData.linkText.isEmpty() && contextMenuData.linkUrl.isValid()) { @@ -331,6 +342,11 @@ void QQuickWebEngineViewPrivate::runGeolocationPermissionRequest(const QUrl &url Q_EMIT q->featurePermissionRequested(url, QQuickWebEngineView::Geolocation); } +void QQuickWebEngineViewPrivate::showColorDialog(QSharedPointer<ColorChooserController> controller) +{ + ui()->showColorDialog(controller); +} + void QQuickWebEngineViewPrivate::runFileChooser(FilePickerController* controller) { ui()->showFilePicker(controller); @@ -379,6 +395,12 @@ void QQuickWebEngineViewPrivate::didUpdateTargetURL(const QUrl &hoveredUrl) Q_EMIT q->linkHovered(hoveredUrl); } +void QQuickWebEngineViewPrivate::wasRecentlyAudibleChanged(bool wasRecentlyAudible) +{ + Q_Q(QQuickWebEngineView); + Q_EMIT q->wasRecentlyAudibleChanged(wasRecentlyAudible); +} + QRectF QQuickWebEngineViewPrivate::viewportRect() const { Q_Q(const QQuickWebEngineView); @@ -607,6 +629,11 @@ BrowserContextAdapter *QQuickWebEngineViewPrivate::browserContextAdapter() return m_profile->d_ptr->browserContext(); } +WebContentsAdapter *QQuickWebEngineViewPrivate::webContentsAdapter() +{ + return adapter.data(); +} + WebEngineSettings *QQuickWebEngineViewPrivate::webEngineSettings() const { return m_settings->d_ptr.data(); @@ -734,7 +761,8 @@ QQuickWebEngineView::QQuickWebEngineView(QQuickItem *parent) Q_D(QQuickWebEngineView); d->e->q_ptr = d->q_ptr = this; this->setActiveFocusOnTab(true); - this->setFlags(QQuickItem::ItemIsFocusScope | QQuickItem::ItemAcceptsInputMethod); + this->setFlags(QQuickItem::ItemIsFocusScope | QQuickItem::ItemAcceptsInputMethod + | QQuickItem::ItemAcceptsDrops); #ifndef QT_NO_ACCESSIBILITY QQuickAccessibleAttached *accessible = QQuickAccessibleAttached::qmlAttachedProperties(this); @@ -975,6 +1003,18 @@ void QQuickWebEngineViewPrivate::moveValidationMessage(const QRect &anchor) ui()->moveMessageBubble(anchor); } +void QQuickWebEngineViewPrivate::updateScrollPosition(const QPointF &position) +{ + Q_Q(QQuickWebEngineView); + Q_EMIT q->scrollPositionChanged(position); +} + +void QQuickWebEngineViewPrivate::updateContentsSize(const QSizeF &size) +{ + Q_Q(QQuickWebEngineView); + Q_EMIT q->contentsSizeChanged(size); +} + void QQuickWebEngineViewPrivate::renderProcessTerminated( RenderProcessTerminationStatus terminationStatus, int exitCode) { @@ -983,6 +1023,13 @@ void QQuickWebEngineViewPrivate::renderProcessTerminated( renderProcessExitStatus(terminationStatus)), exitCode); } +void QQuickWebEngineViewPrivate::startDragging(const content::DropData &dropData, + Qt::DropActions allowedActions, + const QPixmap &pixmap, const QPoint &offset) +{ + adapter->startDragging(q_ptr->window(), dropData, allowedActions, pixmap, offset); +} + bool QQuickWebEngineView::isLoading() const { Q_D(const QQuickWebEngineView); @@ -1024,10 +1071,22 @@ void QQuickWebEngineView::runJavaScript(const QString &script, const QJSValue &c Q_D(QQuickWebEngineView); d->ensureContentsAdapter(); if (!callback.isUndefined()) { - quint64 requestId = d_ptr->adapter->runJavaScriptCallbackResult(script); + quint64 requestId = d_ptr->adapter->runJavaScriptCallbackResult(script, QQuickWebEngineScript::MainWorld); d->m_callbacks.insert(requestId, callback); } else - d->adapter->runJavaScript(script); + d->adapter->runJavaScript(script, QQuickWebEngineScript::MainWorld); +} + +void QQuickWebEngineView::runJavaScript(const QString &script, quint32 worldId, const QJSValue &callback) +{ + Q_D(QQuickWebEngineView); + if (!d->adapter) + return; + if (!callback.isUndefined()) { + quint64 requestId = d_ptr->adapter->runJavaScriptCallbackResult(script, worldId); + d->m_callbacks.insert(requestId, callback); + } else + d->adapter->runJavaScript(script, worldId); } QQuickWebEngineViewExperimental *QQuickWebEngineView::experimental() const @@ -1073,6 +1132,33 @@ void QQuickWebEngineView::setBackgroundColor(const QColor &color) emit backgroundColorChanged(); } +/*! + \property QQuickWebEngineView::audioMuted + \brief the state of whether the current page audio is muted. + \since 5.7 + + The default value is false. +*/ +bool QQuickWebEngineView::isAudioMuted() const { + const Q_D(QQuickWebEngineView); + return d->adapter->isAudioMuted(); + +} +void QQuickWebEngineView::setAudioMuted(bool muted) { + Q_D(QQuickWebEngineView); + bool _isAudioMuted = isAudioMuted(); + d->adapter->setAudioMuted(muted); + if (_isAudioMuted != muted) { + Q_EMIT audioMutedChanged(muted); + } +} + +bool QQuickWebEngineView::wasRecentlyAudible() +{ + Q_D(QQuickWebEngineView); + return d->adapter->wasRecentlyAudible(); +} + bool QQuickWebEngineView::isFullScreen() const { Q_D(const QQuickWebEngineView); @@ -1219,6 +1305,39 @@ void QQuickWebEngineView::itemChange(ItemChange change, const ItemChangeData &va QQuickItem::itemChange(change, value); } +static QPoint mapToScreen(const QQuickItem *item, const QPoint &clientPos) +{ + return item->window()->position() + item->mapToScene(clientPos).toPoint(); +} + +void QQuickWebEngineView::dragEnterEvent(QDragEnterEvent *e) +{ + Q_D(QQuickWebEngineView); + e->accept(); + d->adapter->enterDrag(e, mapToScreen(this, e->pos())); +} + +void QQuickWebEngineView::dragLeaveEvent(QDragLeaveEvent *e) +{ + Q_D(QQuickWebEngineView); + e->accept(); + d->adapter->leaveDrag(); +} + +void QQuickWebEngineView::dragMoveEvent(QDragMoveEvent *e) +{ + Q_D(QQuickWebEngineView); + e->accept(); + d->adapter->updateDragPosition(e, mapToScreen(this, e->pos())); +} + +void QQuickWebEngineView::dropEvent(QDropEvent *e) +{ + Q_D(QQuickWebEngineView); + e->accept(); + d->adapter->endDragging(e->pos(), mapToScreen(this, e->pos())); +} + void QQuickWebEngineView::triggerWebAction(WebAction action) { Q_D(QQuickWebEngineView); @@ -1259,6 +1378,9 @@ void QQuickWebEngineView::triggerWebAction(WebAction action) case PasteAndMatchStyle: d->adapter->pasteAndMatchStyle(); break; + case Unselect: + d->adapter->unselect(); + break; case OpenLinkInThisWindow: if (d->contextMenuData.linkUrl.isValid()) setUrl(d->contextMenuData.linkUrl); @@ -1379,11 +1501,26 @@ void QQuickWebEngineView::triggerWebAction(WebAction action) case RequestClose: d->adapter->requestClose(); break; + case SavePage: + d->adapter->save(); + break; default: Q_UNREACHABLE(); } } +QSizeF QQuickWebEngineView::contentsSize() const +{ + Q_D(const QQuickWebEngineView); + return d->adapter->lastContentsSize(); +} + +QPointF QQuickWebEngineView::scrollPosition() const +{ + Q_D(const QQuickWebEngineView); + return d->adapter->lastScrollOffset(); +} + void QQuickWebEngineViewPrivate::userScripts_append(QQmlListProperty<QQuickWebEngineScript> *p, QQuickWebEngineScript *script) { Q_ASSERT(p && p->data); diff --git a/src/webengine/api/qquickwebengineview_p.h b/src/webengine/api/qquickwebengineview_p.h index 98d0bbc1d..43cdcb73e 100644 --- a/src/webengine/api/qquickwebengineview_p.h +++ b/src/webengine/api/qquickwebengineview_p.h @@ -88,7 +88,7 @@ private: const bool m_toggleOn; }; -#define LATEST_WEBENGINEVIEW_REVISION 2 +#define LATEST_WEBENGINEVIEW_REVISION 3 class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineView : public QQuickItem { Q_OBJECT @@ -108,6 +108,9 @@ class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineView : public QQuickItem { Q_PROPERTY(QQmlListProperty<QQuickWebEngineScript> userScripts READ userScripts FINAL REVISION 1) Q_PROPERTY(bool activeFocusOnPress READ activeFocusOnPress WRITE setActiveFocusOnPress NOTIFY activeFocusOnPressChanged REVISION 2) Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor NOTIFY backgroundColorChanged REVISION 2) + Q_PROPERTY(QSizeF contentsSize READ contentsSize NOTIFY contentsSizeChanged FINAL REVISION 3) + Q_PROPERTY(QPointF scrollPosition READ scrollPosition NOTIFY scrollPositionChanged FINAL REVISION 3) + Q_PROPERTY(bool audioMuted READ isAudioMuted WRITE setAudioMuted NOTIFY audioMutedChanged REVISION 3) #ifdef ENABLE_QML_TESTSUPPORT_API Q_PROPERTY(QQuickWebEngineTestSupport *testSupport READ testSupport WRITE setTestSupport FINAL) @@ -132,6 +135,8 @@ public: void setZoomFactor(qreal arg); QColor backgroundColor() const; void setBackgroundColor(const QColor &color); + QSizeF contentsSize() const; + QPointF scrollPosition() const; QQuickWebEngineViewExperimental *experimental() const; @@ -228,6 +233,8 @@ public: InspectElement, ExitFullScreen, RequestClose, + Unselect, + SavePage, WebActionCount }; @@ -277,6 +284,7 @@ public: public Q_SLOTS: void runJavaScript(const QString&, const QJSValue & = QJSValue()); + Q_REVISION(3) void runJavaScript(const QString&, quint32 worldId, const QJSValue & = QJSValue()); void loadHtml(const QString &html, const QUrl &baseUrl = QUrl()); void goBack(); void goForward(); @@ -289,6 +297,9 @@ public Q_SLOTS: Q_REVISION(1) void grantFeaturePermission(const QUrl &securityOrigin, Feature, bool granted); Q_REVISION(2) void setActiveFocusOnPress(bool arg); Q_REVISION(2) void triggerWebAction(WebAction action); + Q_REVISION(3) bool isAudioMuted() const; + Q_REVISION(3) void setAudioMuted(bool muted); + Q_REVISION(3) bool wasRecentlyAudible(); private Q_SLOTS: void lazyInitialize(); @@ -314,10 +325,18 @@ Q_SIGNALS: Q_REVISION(2) void backgroundColorChanged(); Q_REVISION(2) void renderProcessTerminated(RenderProcessTerminationStatus terminationStatus, int exitCode); Q_REVISION(2) void windowCloseRequested(); + Q_REVISION(3) void contentsSizeChanged(const QSizeF& size); + Q_REVISION(3) void scrollPositionChanged(const QPointF& position); + Q_REVISION(3) void audioMutedChanged(bool muted); + Q_REVISION(3) void wasRecentlyAudibleChanged(bool wasRecentlyAudible); protected: void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); void itemChange(ItemChange, const ItemChangeData &); + void dragEnterEvent(QDragEnterEvent *e) Q_DECL_OVERRIDE; + void dragLeaveEvent(QDragLeaveEvent *e) Q_DECL_OVERRIDE; + void dragMoveEvent(QDragMoveEvent *e) Q_DECL_OVERRIDE; + void dropEvent(QDropEvent *e) Q_DECL_OVERRIDE; private: Q_DECLARE_PRIVATE(QQuickWebEngineView) diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h index 5d3be5216..dd20c8972 100644 --- a/src/webengine/api/qquickwebengineview_p_p.h +++ b/src/webengine/api/qquickwebengineview_p_p.h @@ -132,6 +132,7 @@ public: virtual void loadProgressChanged(int progress) Q_DECL_OVERRIDE; virtual void didUpdateTargetURL(const QUrl&) Q_DECL_OVERRIDE; virtual void selectionChanged() Q_DECL_OVERRIDE { } + virtual void wasRecentlyAudibleChanged(bool wasRecentlyAudible) Q_DECL_OVERRIDE; virtual QRectF viewportRect() const Q_DECL_OVERRIDE; virtual qreal dpiScale() const Q_DECL_OVERRIDE; virtual QColor backgroundColor() const Q_DECL_OVERRIDE; @@ -151,6 +152,7 @@ public: virtual void navigationRequested(int navigationType, const QUrl &url, int &navigationRequestAction, bool isMainFrame) Q_DECL_OVERRIDE; virtual void javascriptDialog(QSharedPointer<QtWebEngineCore::JavaScriptDialogController>) Q_DECL_OVERRIDE; virtual void runFileChooser(QtWebEngineCore::FilePickerController *controller) Q_DECL_OVERRIDE; + virtual void showColorDialog(QSharedPointer<QtWebEngineCore::ColorChooserController>) Q_DECL_OVERRIDE; virtual void didRunJavaScript(quint64, const QVariant&) Q_DECL_OVERRIDE; virtual void didFetchDocumentMarkup(quint64, const QString&) Q_DECL_OVERRIDE { } virtual void didFetchDocumentInnerText(quint64, const QString&) Q_DECL_OVERRIDE { } @@ -171,8 +173,13 @@ public: virtual void moveValidationMessage(const QRect &anchor) Q_DECL_OVERRIDE; virtual void renderProcessTerminated(RenderProcessTerminationStatus terminationStatus, int exitCode) Q_DECL_OVERRIDE; + virtual void updateScrollPosition(const QPointF &position) Q_DECL_OVERRIDE; + virtual void updateContentsSize(const QSizeF &size) Q_DECL_OVERRIDE; + 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; + QtWebEngineCore::WebContentsAdapter *webContentsAdapter() Q_DECL_OVERRIDE; void setDevicePixelRatio(qreal); void adoptWebContents(QtWebEngineCore::WebContentsAdapter *webContents); diff --git a/src/webengine/doc/src/qtwebengine-overview.qdoc b/src/webengine/doc/src/qtwebengine-overview.qdoc index 50d03a9f4..ca60fedc2 100644 --- a/src/webengine/doc/src/qtwebengine-overview.qdoc +++ b/src/webengine/doc/src/qtwebengine-overview.qdoc @@ -155,6 +155,18 @@ The functions can be used to synchronize cookies with QNetworkAccessManager, as well as to set, delete, and intercept cookies during navigation. + \section1 Deploying Qt WebEngine Applications + + Qt WebEngine takes advantage of the multi process model that the Chromium project offers. + The multi process model requires the QtWebEngineProcess executable to be deployed alongside your application. + To do this, we recommend the use of Qt’s cross-platform deployment tools. + + Alternatively, if you are carrying out manual deployment, you will find the QtWebEngineProcess executable in the + libexec directory of your Qt installation. + On Windows, QtWebEngineProcess.exe is located in the bin directory of your Qt application. + + For more information on deploying Qt applications, please see \l {Deploying Qt Applications}. + \section1 License Information Qt WebEngine module is a snapshot of the integration of Chromium into Qt. diff --git a/src/webengine/doc/src/webengineview.qdoc b/src/webengine/doc/src/webengineview.qdoc index bfdeab984..39441228d 100644 --- a/src/webengine/doc/src/webengineview.qdoc +++ b/src/webengine/doc/src/webengineview.qdoc @@ -671,6 +671,8 @@ (Added in Qt 5.6) \value ExitFullScreen Exit the fullscreen mode. (Added in Qt 5.6) + \value SavePage + Save the current web page to disk. (Added in Qt 5.7) \omitvalue WebActionCount */ @@ -738,3 +740,37 @@ \sa toggleOn */ + +/*! + \qmlproperty bool WebEngineView::audioMuted + \brief The state of whether the current page audio is muted. + \since QtWebEngine 1.3 +*/ + +/*! + \qmlsignal void WebEngineView::audioMutedChanged(bool muted) + \since QtWebEngine 1.3 + + This signal is emitted when the page's audio is (un)muted using setAudioMuted method. + \note Not to be confused with a specific HTML5 audio / video element being muted. +*/ + +/*! + \qmlmethod bool WebEngineView::wasRecentlyAudible() + \since QtWebEngine 1.3 + \sa wasRecentlyAudibleChanged() + + Returns the current page's audible state (audio was recently played, or not). +*/ + +/*! + \qmlsignal void WebEngineView::wasRecentlyAudibleChanged(bool wasRecentlyAudible) + \since QtWebEngine 1.3 + + This signal is emitted when the page's audible state is changed, due to audio + being played or stopped. + + \note The signal is also emitted when calling the setAudioMuted method. + Also if the audio is paused, this signal is emitted with an approximate \b{2 second + delay}, from the moment the audio is paused. +*/ diff --git a/src/webengine/plugin/plugin.cpp b/src/webengine/plugin/plugin.cpp index ca4fb2e74..5eee75e7f 100644 --- a/src/webengine/plugin/plugin.cpp +++ b/src/webengine/plugin/plugin.cpp @@ -70,6 +70,7 @@ public: qmlRegisterType<QQuickWebEngineView, 1>(uri, 1, 1, "WebEngineView"); qmlRegisterType<QQuickWebEngineView, 2>(uri, 1, 2, "WebEngineView"); + qmlRegisterType<QQuickWebEngineView, 3>(uri, 1, 3, "WebEngineView"); qmlRegisterType<QQuickWebEngineProfile>(uri, 1, 1, "WebEngineProfile"); qmlRegisterType<QQuickWebEngineProfile, 1>(uri, 1, 2, "WebEngineProfile"); qmlRegisterType<QQuickWebEngineScript>(uri, 1, 1, "WebEngineScript"); diff --git a/src/webengine/ui/ColorDialog.qml b/src/webengine/ui/ColorDialog.qml new file mode 100644 index 000000000..27245d7f7 --- /dev/null +++ b/src/webengine/ui/ColorDialog.qml @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2015 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick.Dialogs 1.2 + +ColorDialog { + id: colorDialog + + signal selectedColor(var color) + + onAccepted: { + selectedColor(colorDialog.currentColor) + } +} diff --git a/src/webengine/ui/ui.pro b/src/webengine/ui/ui.pro index 28ea691b2..249d7dcfd 100644 --- a/src/webengine/ui/ui.pro +++ b/src/webengine/ui/ui.pro @@ -5,6 +5,7 @@ QML_FILES += \ AuthenticationDialog.qml \ # JS Dialogs AlertDialog.qml \ + ColorDialog.qml \ ConfirmDialog.qml \ FilePicker.qml \ PromptDialog.qml \ diff --git a/src/webengine/ui_delegates_manager.cpp b/src/webengine/ui_delegates_manager.cpp index 64e22c4a9..b9162f9b9 100644 --- a/src/webengine/ui_delegates_manager.cpp +++ b/src/webengine/ui_delegates_manager.cpp @@ -37,14 +37,13 @@ #include "ui_delegates_manager.h" #include "api/qquickwebengineview_p.h" -#include "authentication_dialog_controller.h" -#include "file_picker_controller.h" -#include "javascript_dialog_controller.h" +#include <authentication_dialog_controller.h> +#include <color_chooser_controller.h> +#include <file_picker_controller.h> +#include <javascript_dialog_controller.h> +#include <web_contents_adapter_client.h> -#include <QAbstractListModel> -#include <QClipboard> #include <QFileInfo> -#include <QMimeData> #include <QQmlContext> #include <QQmlEngine> #include <QQmlProperty> @@ -323,6 +322,43 @@ void UIDelegatesManager::showDialog(QSharedPointer<JavaScriptDialogController> d QMetaObject::invokeMethod(dialog, "open"); } +void UIDelegatesManager::showColorDialog(QSharedPointer<ColorChooserController> controller) +{ + if (!ensureComponentLoaded(ColorDialog)) { + // Let the controller know it couldn't be loaded + qWarning("Failed to load dialog, rejecting."); + controller->reject(); + return; + } + + QQmlContext *context = qmlContext(m_view); + QObject *colorDialog = colorDialogComponent->beginCreate(context); + if (QQuickItem* item = qobject_cast<QQuickItem*>(colorDialog)) + item->setParentItem(m_view); + colorDialog->setParent(m_view); + + if (controller->initialColor().isValid()) + colorDialog->setProperty("color", controller->initialColor()); + + QQmlProperty selectedColorSignal(colorDialog, QStringLiteral("onSelectedColor")); + CHECK_QML_SIGNAL_PROPERTY(selectedColorSignal, colorDialogComponent->url()); + QQmlProperty rejectedSignal(colorDialog, QStringLiteral("onRejected")); + CHECK_QML_SIGNAL_PROPERTY(rejectedSignal, colorDialogComponent->url()); + + static int acceptIndex = controller->metaObject()->indexOfSlot("accept(QVariant)"); + QObject::connect(colorDialog, selectedColorSignal.method(), controller.data(), controller->metaObject()->method(acceptIndex)); + static int rejectIndex = controller->metaObject()->indexOfSlot("reject()"); + QObject::connect(colorDialog, rejectedSignal.method(), controller.data(), controller->metaObject()->method(rejectIndex)); + + // delete later + static int deleteLaterIndex = colorDialog->metaObject()->indexOfSlot("deleteLater()"); + QObject::connect(colorDialog, selectedColorSignal.method(), colorDialog, colorDialog->metaObject()->method(deleteLaterIndex)); + QObject::connect(colorDialog, rejectedSignal.method(), colorDialog, colorDialog->metaObject()->method(deleteLaterIndex)); + + colorDialogComponent->completeCreate(); + QMetaObject::invokeMethod(colorDialog, "open"); +} + void UIDelegatesManager::showDialog(QSharedPointer<AuthenticationDialogController> dialogController) { Q_ASSERT(!dialogController.isNull()); diff --git a/src/webengine/ui_delegates_manager.h b/src/webengine/ui_delegates_manager.h index 5eeaf6e03..71d2e2fb0 100644 --- a/src/webengine/ui_delegates_manager.h +++ b/src/webengine/ui_delegates_manager.h @@ -44,15 +44,14 @@ #include <QCoreApplication> #include <QExplicitlySharedDataPointer> #include <QPoint> -#include <QQmlComponent> #include <QSharedPointer> -#include <QUrl> #define FOR_EACH_COMPONENT_TYPE(F, SEPARATOR) \ F(Menu, menu) SEPARATOR \ F(MenuItem, menuItem) SEPARATOR \ F(MenuSeparator, menuSeparator) SEPARATOR \ F(AlertDialog, alertDialog) SEPARATOR \ + F(ColorDialog, colorDialog) SEPARATOR \ F(ConfirmDialog, confirmDialog) SEPARATOR \ F(PromptDialog, promptDialog) SEPARATOR \ F(FilePicker, filePicker) SEPARATOR \ @@ -67,8 +66,8 @@ QQmlComponent *COMPONENT##Component QT_BEGIN_NAMESPACE -class QObject; class QQmlContext; +class QQmlComponent; class QQuickItem; class QQuickWebEngineView; QT_END_NAMESPACE @@ -105,6 +104,7 @@ public: void addMenuSeparator(QObject *menu); QObject *addMenu(QObject *parentMenu, const QString &title, const QPoint &pos = QPoint()); QQmlContext *creationContextForComponent(QQmlComponent *); + void showColorDialog(QSharedPointer<ColorChooserController>); void showDialog(QSharedPointer<JavaScriptDialogController>); void showDialog(QSharedPointer<AuthenticationDialogController>); void showFilePicker(FilePickerController *controller); diff --git a/src/webenginewidgets/api/qtwebenginewidgetsglobal.cpp b/src/webenginewidgets/api/qtwebenginewidgetsglobal.cpp index 1ef6386ad..b1a8f7b78 100644 --- a/src/webenginewidgets/api/qtwebenginewidgetsglobal.cpp +++ b/src/webenginewidgets/api/qtwebenginewidgetsglobal.cpp @@ -37,6 +37,7 @@ #include "qtwebenginewidgetsglobal.h" #include <QCoreApplication> +#include <QOpenGLContext> namespace QtWebEngineCore { @@ -46,9 +47,18 @@ namespace QtWebEngineCore QT_BEGIN_NAMESPACE static void initialize() { - QtWebEngineCore::initialize(); + //On window/ANGLE, calling QtWebEngine::initialize from DllMain will result in a crash. + //To ensure it doesn't, we check that when loading the library + //QCoreApplication is not yet instantiated, ensuring the call will be deferred +#if defined(Q_OS_WIN) + if (QCoreApplication::instance() + && QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) { + return; + } +#endif + qAddPreRoutine(QtWebEngineCore::initialize); } -Q_COREAPP_STARTUP_FUNCTION(initialize) +Q_CONSTRUCTOR_FUNCTION(initialize) QT_END_NAMESPACE diff --git a/src/webenginewidgets/api/qwebenginedownloaditem.cpp b/src/webenginewidgets/api/qwebenginedownloaditem.cpp index 9fdab3367..bc7e3932c 100644 --- a/src/webenginewidgets/api/qwebenginedownloaditem.cpp +++ b/src/webenginewidgets/api/qwebenginedownloaditem.cpp @@ -76,6 +76,7 @@ QWebEngineDownloadItemPrivate::QWebEngineDownloadItemPrivate(QWebEngineProfilePr , downloadFinished(false) , downloadId(-1) , downloadState(QWebEngineDownloadItem::DownloadCancelled) + , savePageFormat(QWebEngineDownloadItem::MimeHtmlSaveFormat) , downloadUrl(url) , totalBytes(-1) , receivedBytes(0) @@ -201,6 +202,19 @@ quint32 QWebEngineDownloadItem::id() const */ /*! + \enum QWebEngineDownloadItem::SavePageFormat + + This enum describes the format that is used to save a web page. + + \value UnknownSaveFormat This is not a request for downloading a complete web page. + \value SingleHtmlSaveFormat The page is saved as a single HTML page. Resources such as images + are not saved. + \value CompleteHtmlSaveFormat The page is saved as a complete HTML page, for example a directory + containing the single HTML page and the resources. + \value MimeHtmlSaveFormat The page is saved as a complete web page in the MIME HTML format. +*/ + +/*! Returns the download item's current state. \sa QWebEngineDownloadItem::DownloadState @@ -301,6 +315,28 @@ bool QWebEngineDownloadItem::isFinished() const return d->downloadFinished; } +/*! + Returns the format the web page will be saved in if this is a download request for a web page. + + \sa setSavePageFormat() +*/ +QWebEngineDownloadItem::SavePageFormat QWebEngineDownloadItem::savePageFormat() const +{ + Q_D(const QWebEngineDownloadItem); + return d->savePageFormat; +} + +/*! + Sets the format the web page will be saved in if this is a download request for a web page. + + \sa savePageFormat() +*/ +void QWebEngineDownloadItem::setSavePageFormat(QWebEngineDownloadItem::SavePageFormat format) +{ + Q_D(QWebEngineDownloadItem); + d->savePageFormat = format; +} + QWebEngineDownloadItem::QWebEngineDownloadItem(QWebEngineDownloadItemPrivate *p, QObject *parent) : QObject(parent) , d_ptr(p) diff --git a/src/webenginewidgets/api/qwebenginedownloaditem.h b/src/webenginewidgets/api/qwebenginedownloaditem.h index 886d9ab9a..b1c00f28a 100644 --- a/src/webenginewidgets/api/qwebenginedownloaditem.h +++ b/src/webenginewidgets/api/qwebenginedownloaditem.h @@ -61,6 +61,14 @@ public: }; Q_ENUM(DownloadState) + enum SavePageFormat { + UnknownSaveFormat = -1, + SingleHtmlSaveFormat, + CompleteHtmlSaveFormat, + MimeHtmlSaveFormat + }; + Q_ENUM(SavePageFormat) + quint32 id() const; DownloadState state() const; qint64 totalBytes() const; @@ -70,6 +78,8 @@ public: QString path() const; void setPath(QString path); bool isFinished() const; + SavePageFormat savePageFormat() const; + void setSavePageFormat(SavePageFormat format); public Q_SLOTS: void accept(); diff --git a/src/webenginewidgets/api/qwebenginedownloaditem_p.h b/src/webenginewidgets/api/qwebenginedownloaditem_p.h index 2c7bbf985..cb8bbf000 100644 --- a/src/webenginewidgets/api/qwebenginedownloaditem_p.h +++ b/src/webenginewidgets/api/qwebenginedownloaditem_p.h @@ -68,6 +68,7 @@ public: bool downloadFinished; quint32 downloadId; QWebEngineDownloadItem::DownloadState downloadState; + QWebEngineDownloadItem::SavePageFormat savePageFormat; QString downloadPath; const QUrl downloadUrl; QString mimeType; diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index f8f96af6a..d97cb5a09 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -26,6 +26,7 @@ #include "authentication_dialog_controller.h" #include "browser_context_adapter.h" #include "certificate_error_controller.h" +#include "color_chooser_controller.h" #include "file_picker_controller.h" #include "javascript_dialog_controller.h" #include "qwebenginefullscreenrequest.h" @@ -49,6 +50,7 @@ #include <QApplication> #include <QAuthenticator> #include <QClipboard> +#include <QColorDialog> #include <QContextMenuEvent> #include <QFileDialog> #include <QKeyEvent> @@ -145,6 +147,12 @@ void QWebEnginePagePrivate::selectionChanged() Q_EMIT q->selectionChanged(); } +void QWebEnginePagePrivate::wasRecentlyAudibleChanged(bool wasRecentlyAudible) +{ + Q_Q(QWebEnginePage); + Q_EMIT q->wasRecentlyAudibleChanged(wasRecentlyAudible); +} + QRectF QWebEnginePagePrivate::viewportRect() const { return view ? view->rect() : QRectF(); @@ -299,6 +307,20 @@ void QWebEnginePagePrivate::authenticationRequired(QSharedPointer<Authentication controller->accept(networkAuth.user(), networkAuth.password()); } +void QWebEnginePagePrivate::showColorDialog(QSharedPointer<ColorChooserController> controller) +{ + QColorDialog *dialog = new QColorDialog(controller.data()->initialColor(), view); + + QColorDialog::connect(dialog, SIGNAL(colorSelected(QColor)), controller.data(), SLOT(accept(QColor))); + QColorDialog::connect(dialog, SIGNAL(rejected()), controller.data(), SLOT(reject())); + + // Delete when done + QColorDialog::connect(dialog, SIGNAL(colorSelected(QColor)), dialog, SLOT(deleteLater())); + QColorDialog::connect(dialog, SIGNAL(rejected()), dialog, SLOT(deleteLater())); + + dialog->open(); +} + void QWebEnginePagePrivate::runMediaAccessPermissionRequest(const QUrl &securityOrigin, WebContentsAdapterClient::MediaRequestFlags requestFlags) { Q_Q(QWebEnginePage); @@ -396,6 +418,18 @@ void QWebEnginePagePrivate::recreateFromSerializedHistory(QDataStream &input) } } +void QWebEnginePagePrivate::updateScrollPosition(const QPointF &position) +{ + Q_Q(QWebEnginePage); + Q_EMIT q->scrollPositionChanged(position); +} + +void QWebEnginePagePrivate::updateContentsSize(const QSizeF &size) +{ + Q_Q(QWebEnginePage); + Q_EMIT q->contentsSizeChanged(size); +} + void QWebEnginePagePrivate::setFullScreenMode(bool fullscreen) { if (fullscreenMode != fullscreen) { @@ -409,6 +443,11 @@ BrowserContextAdapter *QWebEnginePagePrivate::browserContextAdapter() return profile->d_ptr->browserContext(); } +WebContentsAdapter *QWebEnginePagePrivate::webContentsAdapter() +{ + return adapter.data(); +} + QWebEnginePage::QWebEnginePage(QObject* parent) : QObject(parent) , d_ptr(new QWebEnginePagePrivate()) @@ -457,6 +496,20 @@ QWebEnginePage::QWebEnginePage(QObject* parent) */ /*! + \property QWebEnginePage::scrollPosition + \since 5.7 + + \brief The scroll position of the page contents. +*/ + +/*! + \property QWebEnginePage::contentsSize + \since 5.7 + + The size of the page contents. +*/ + +/*! Constructs an empty web engine page in the web engine profile \a profile with the parent \a parent. @@ -550,6 +603,33 @@ void QWebEnginePage::setBackgroundColor(const QColor &color) d->adapter->backgroundColorChanged(); } +/*! + \property QWebEnginePage::audioMuted + \brief the state of whether the current page audio is muted. + \since 5.7 + + The default value is false. +*/ +bool QWebEnginePage::isAudioMuted() const { + const Q_D(QWebEnginePage); + return d->adapter->isAudioMuted(); +} + +void QWebEnginePage::setAudioMuted(bool muted) { + Q_D(QWebEnginePage); + bool _isAudioMuted = isAudioMuted(); + d->adapter->setAudioMuted(muted); + if (_isAudioMuted != muted) { + Q_EMIT audioMutedChanged(muted); + } +} + +bool QWebEnginePage::wasRecentlyAudible() +{ + Q_D(QWebEnginePage); + return d->adapter->wasRecentlyAudible(); +} + void QWebEnginePage::setView(QWidget *view) { QWebEngineViewPrivate::bind(qobject_cast<QWebEngineView*>(view), this); @@ -684,6 +764,12 @@ QAction *QWebEnginePage::action(WebAction action) const case RequestClose: text = tr("Close Page"); break; + case Unselect: + text = tr("Unselect"); + break; + case SavePage: + text = tr("Save &Page"); + break; default: break; } @@ -741,6 +827,9 @@ void QWebEnginePage::triggerAction(WebAction action, bool) case PasteAndMatchStyle: d->adapter->pasteAndMatchStyle(); break; + case Unselect: + d->adapter->unselect(); + break; case OpenLinkInThisWindow: if (d->m_menuData.linkUrl.isValid()) setUrl(d->m_menuData.linkUrl); @@ -844,7 +933,8 @@ void QWebEnginePage::triggerAction(WebAction action, bool) break; case ToggleMediaMute: if (d->m_menuData.mediaUrl.isValid() && d->m_menuData.mediaFlags & WebEngineContextMenuData::MediaHasAudio) { - bool enable = (d->m_menuData.mediaFlags & WebEngineContextMenuData::MediaMuted); + // Make sure to negate the value, so that toggling actually works. + bool enable = !(d->m_menuData.mediaFlags & WebEngineContextMenuData::MediaMuted); d->adapter->executeMediaPlayerActionAt(d->m_menuData.pos, WebContentsAdapter::MediaPlayerMute, enable); } break; @@ -857,6 +947,9 @@ void QWebEnginePage::triggerAction(WebAction action, bool) case RequestClose: d->adapter->requestClose(); break; + case SavePage: + d->adapter->save(); + break; default: Q_UNREACHABLE(); } @@ -1023,6 +1116,13 @@ void QWebEnginePagePrivate::renderProcessTerminated(RenderProcessTerminationStat terminationStatus), exitCode); } +void QWebEnginePagePrivate::startDragging(const content::DropData &dropData, + Qt::DropActions allowedActions, const QPixmap &pixmap, + const QPoint &offset) +{ + adapter->startDragging(view, dropData, allowedActions, pixmap, offset); +} + QMenu *QWebEnginePage::createStandardContextMenu() { Q_D(QWebEnginePage); @@ -1049,8 +1149,12 @@ QMenu *QWebEnginePage::createStandardContextMenu() action = new QAction(QIcon::fromTheme(QStringLiteral("view-refresh")), tr("&Reload"), menu); connect(action, &QAction::triggered, d->view, &QWebEngineView::reload); menu->addAction(action); + + if (!contextMenuData.linkUrl.isValid()) + menu->addAction(QWebEnginePage::action(SavePage)); } else { menu->addAction(QWebEnginePage::action(Copy)); + menu->addAction(QWebEnginePage::action(Unselect)); } if (!contextMenuData.linkText.isEmpty() && contextMenuData.linkUrl.isValid()) { @@ -1232,13 +1336,26 @@ void QWebEnginePage::setZoomFactor(qreal factor) void QWebEnginePage::runJavaScript(const QString &scriptSource) { Q_D(QWebEnginePage); - d->adapter->runJavaScript(scriptSource); + d->adapter->runJavaScript(scriptSource, QWebEngineScript::MainWorld); } void QWebEnginePage::runJavaScript(const QString& scriptSource, const QWebEngineCallback<const QVariant &> &resultCallback) { Q_D(QWebEnginePage); - quint64 requestId = d->adapter->runJavaScriptCallbackResult(scriptSource); + quint64 requestId = d->adapter->runJavaScriptCallbackResult(scriptSource, QWebEngineScript::MainWorld); + d->m_callbacks.registerCallback(requestId, resultCallback); +} + +void QWebEnginePage::runJavaScript(const QString &scriptSource, quint32 worldId) +{ + Q_D(QWebEnginePage); + d->adapter->runJavaScript(scriptSource, worldId); +} + +void QWebEnginePage::runJavaScript(const QString& scriptSource, quint32 worldId, const QWebEngineCallback<const QVariant &> &resultCallback) +{ + Q_D(QWebEnginePage); + quint64 requestId = d->adapter->runJavaScriptCallbackResult(scriptSource, worldId); d->m_callbacks.registerCallback(requestId, resultCallback); } @@ -1359,6 +1476,18 @@ bool QWebEnginePage::acceptNavigationRequest(const QUrl &url, NavigationType typ return true; } +QPointF QWebEnginePage::scrollPosition() const +{ + Q_D(const QWebEnginePage); + return d->adapter->lastScrollOffset(); +} + +QSizeF QWebEnginePage::contentsSize() const +{ + Q_D(const QWebEnginePage); + return d->adapter->lastContentsSize(); +} + QT_END_NAMESPACE #include "moc_qwebenginepage.cpp" diff --git a/src/webenginewidgets/api/qwebenginepage.h b/src/webenginewidgets/api/qwebenginepage.h index 83faaf42e..950ae374a 100644 --- a/src/webenginewidgets/api/qwebenginepage.h +++ b/src/webenginewidgets/api/qwebenginepage.h @@ -70,6 +70,9 @@ class QWEBENGINEWIDGETS_EXPORT QWebEnginePage : public QObject { Q_PROPERTY(QUrl url READ url WRITE setUrl) Q_PROPERTY(QUrl iconUrl READ iconUrl) Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor) + Q_PROPERTY(QSizeF contentsSize READ contentsSize NOTIFY contentsSizeChanged) + Q_PROPERTY(QPointF scrollPosition READ scrollPosition NOTIFY scrollPositionChanged) + Q_PROPERTY(bool audioMuted READ isAudioMuted WRITE setAudioMuted NOTIFY audioMutedChanged) public: enum WebAction { @@ -110,6 +113,8 @@ public: InspectElement, ExitFullScreen, RequestClose, + Unselect, + SavePage, WebActionCount }; @@ -226,11 +231,17 @@ public: qreal zoomFactor() const; void setZoomFactor(qreal factor); + QPointF scrollPosition() const; + QSizeF contentsSize() const; + void runJavaScript(const QString& scriptSource); + void runJavaScript(const QString& scriptSource, quint32 worldId); #ifdef Q_QDOC void runJavaScript(const QString& scriptSource, FunctorOrLambda resultCallback); + void runJavaScript(const QString& scriptSource, quint32 worldId, FunctorOrLambda resultCallback); #else void runJavaScript(const QString& scriptSource, const QWebEngineCallback<const QVariant &> &resultCallback); + void runJavaScript(const QString& scriptSource, quint32 worldId, const QWebEngineCallback<const QVariant &> &resultCallback); #endif QWebEngineScriptCollection &scripts(); QWebEngineSettings *settings() const; @@ -240,6 +251,10 @@ public: QColor backgroundColor() const; void setBackgroundColor(const QColor &color); + bool isAudioMuted() const; + void setAudioMuted(bool muted); + bool wasRecentlyAudible(); + Q_SIGNALS: void loadStarted(); void loadProgress(int progress); @@ -265,6 +280,11 @@ Q_SIGNALS: // Was iconChanged() in QWebFrame void iconUrlChanged(const QUrl &url); + void scrollPositionChanged(const QPointF &position); + void contentsSizeChanged(const QSizeF &size); + void audioMutedChanged(bool muted); + void wasRecentlyAudibleChanged(bool wasRecentlyAudible); + protected: virtual QWebEnginePage *createWindow(WebWindowType type); virtual QStringList chooseFiles(FileSelectionMode mode, const QStringList &oldFiles, const QStringList &acceptedMimeTypes); diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h index 01f7ce42f..3da336369 100644 --- a/src/webenginewidgets/api/qwebenginepage_p.h +++ b/src/webenginewidgets/api/qwebenginepage_p.h @@ -84,6 +84,7 @@ public: virtual void loadProgressChanged(int progress) Q_DECL_OVERRIDE; virtual void didUpdateTargetURL(const QUrl&) Q_DECL_OVERRIDE; virtual void selectionChanged() Q_DECL_OVERRIDE; + virtual void wasRecentlyAudibleChanged(bool wasRecentlyAudible) Q_DECL_OVERRIDE; virtual QRectF viewportRect() const Q_DECL_OVERRIDE; virtual qreal dpiScale() const Q_DECL_OVERRIDE; virtual QColor backgroundColor() const Q_DECL_OVERRIDE; @@ -103,6 +104,7 @@ public: virtual bool isFullScreenMode() const Q_DECL_OVERRIDE; virtual void javascriptDialog(QSharedPointer<QtWebEngineCore::JavaScriptDialogController>) Q_DECL_OVERRIDE; virtual void runFileChooser(QtWebEngineCore::FilePickerController *controller) Q_DECL_OVERRIDE; + virtual void showColorDialog(QSharedPointer<QtWebEngineCore::ColorChooserController>); virtual void didRunJavaScript(quint64 requestId, const QVariant& result) Q_DECL_OVERRIDE; virtual void didFetchDocumentMarkup(quint64 requestId, const QString& result) Q_DECL_OVERRIDE; virtual void didFetchDocumentInnerText(quint64 requestId, const QString& result) Q_DECL_OVERRIDE; @@ -123,8 +125,13 @@ public: virtual void moveValidationMessage(const QRect &anchor) Q_DECL_OVERRIDE; virtual void renderProcessTerminated(RenderProcessTerminationStatus terminationStatus, int exitCode) Q_DECL_OVERRIDE; + virtual void updateScrollPosition(const QPointF &position) Q_DECL_OVERRIDE; + virtual void updateContentsSize(const QSizeF &size) Q_DECL_OVERRIDE; + 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; + QtWebEngineCore::WebContentsAdapter *webContentsAdapter() Q_DECL_OVERRIDE; void updateAction(QWebEnginePage::WebAction) const; void updateNavigationActions(); diff --git a/src/webenginewidgets/api/qwebengineprofile.cpp b/src/webenginewidgets/api/qwebengineprofile.cpp index 7f63b312f..c64a883d3 100644 --- a/src/webenginewidgets/api/qwebengineprofile.cpp +++ b/src/webenginewidgets/api/qwebengineprofile.cpp @@ -45,11 +45,17 @@ #include "qwebenginescriptcollection_p.h" #include "browser_context_adapter.h" +#include <qtwebenginecoreglobal.h> #include "web_engine_visited_links_manager.h" #include "web_engine_settings.h" QT_BEGIN_NAMESPACE +ASSERT_ENUMS_MATCH(QWebEngineDownloadItem::UnknownSaveFormat, QtWebEngineCore::BrowserContextAdapterClient::UnknownSavePageFormat) +ASSERT_ENUMS_MATCH(QWebEngineDownloadItem::SingleHtmlSaveFormat, QtWebEngineCore::BrowserContextAdapterClient::SingleHtmlSaveFormat) +ASSERT_ENUMS_MATCH(QWebEngineDownloadItem::CompleteHtmlSaveFormat, QtWebEngineCore::BrowserContextAdapterClient::CompleteHtmlSaveFormat) +ASSERT_ENUMS_MATCH(QWebEngineDownloadItem::MimeHtmlSaveFormat, QtWebEngineCore::BrowserContextAdapterClient::MimeHtmlSaveFormat) + using QtWebEngineCore::BrowserContextAdapter; /*! @@ -151,6 +157,7 @@ void QWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info) itemPrivate->downloadState = QWebEngineDownloadItem::DownloadRequested; itemPrivate->downloadPath = info.path; itemPrivate->mimeType = info.mimeType; + itemPrivate->savePageFormat = static_cast<QWebEngineDownloadItem::SavePageFormat>(info.savePageFormat); QWebEngineDownloadItem *download = new QWebEngineDownloadItem(itemPrivate, q); @@ -161,6 +168,8 @@ void QWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info) QWebEngineDownloadItem::DownloadState state = download->state(); info.path = download->path(); + info.savePageFormat = static_cast<QtWebEngineCore::BrowserContextAdapterClient::SavePageFormat>( + download->savePageFormat()); info.accepted = state != QWebEngineDownloadItem::DownloadCancelled; if (state == QWebEngineDownloadItem::DownloadRequested) { @@ -621,4 +630,15 @@ void QWebEngineProfile::destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler *ob removeUrlSchemeHandler(obj); } +/*! + \since 5.7 + + Removes the profile's cache entries. +*/ +void QWebEngineProfile::clearHttpCache() +{ + Q_D(QWebEngineProfile); + d->browserContext()->clearHttpCache(); +} + QT_END_NAMESPACE diff --git a/src/webenginewidgets/api/qwebengineprofile.h b/src/webenginewidgets/api/qwebengineprofile.h index 416ef23db..4b37a7d73 100644 --- a/src/webenginewidgets/api/qwebengineprofile.h +++ b/src/webenginewidgets/api/qwebengineprofile.h @@ -115,6 +115,8 @@ public: void removeUrlSchemeHandler(QWebEngineUrlSchemeHandler *); void removeAllUrlSchemeHandlers(); + void clearHttpCache(); + static QWebEngineProfile *defaultProfile(); Q_SIGNALS: diff --git a/src/webenginewidgets/api/qwebenginesettings.cpp b/src/webenginewidgets/api/qwebenginesettings.cpp index 430d64185..ba372d465 100644 --- a/src/webenginewidgets/api/qwebenginesettings.cpp +++ b/src/webenginewidgets/api/qwebenginesettings.cpp @@ -76,6 +76,14 @@ static WebEngineSettings::Attribute toWebEngineAttribute(QWebEngineSettings::Web return WebEngineSettings::PluginsEnabled; case QWebEngineSettings::FullScreenSupportEnabled: return WebEngineSettings::FullScreenSupportEnabled; + case QWebEngineSettings::ScreenCaptureEnabled: + return WebEngineSettings::ScreenCaptureEnabled; + case QWebEngineSettings::WebGLEnabled: + return WebEngineSettings::WebGLEnabled; + case QWebEngineSettings::WebAudioEnabled: + return WebEngineSettings::WebAudioEnabled; + case QWebEngineSettings::Accelerated2dCanvasEnabled: + return WebEngineSettings::Accelerated2dCanvasEnabled; default: return WebEngineSettings::UnsupportedInCoreSettings; } @@ -115,6 +123,7 @@ ASSERT_ENUMS_MATCH(WebEngineSettings::SerifFont, QWebEngineSettings::SerifFont) ASSERT_ENUMS_MATCH(WebEngineSettings::SansSerifFont, QWebEngineSettings::SansSerifFont) ASSERT_ENUMS_MATCH(WebEngineSettings::CursiveFont, QWebEngineSettings::CursiveFont) ASSERT_ENUMS_MATCH(WebEngineSettings::FantasyFont, QWebEngineSettings::FantasyFont) +ASSERT_ENUMS_MATCH(WebEngineSettings::PictographFont, QWebEngineSettings::PictographFont) void QWebEngineSettings::setFontFamily(QWebEngineSettings::FontFamily which, const QString &family) { diff --git a/src/webenginewidgets/api/qwebenginesettings.h b/src/webenginewidgets/api/qwebenginesettings.h index 327fd447b..f236abe94 100644 --- a/src/webenginewidgets/api/qwebenginesettings.h +++ b/src/webenginewidgets/api/qwebenginesettings.h @@ -43,7 +43,8 @@ public: SerifFont, SansSerifFont, CursiveFont, - FantasyFont + FantasyFont, + PictographFont }; enum WebAttribute { AutoLoadImages, @@ -60,7 +61,11 @@ public: ScrollAnimatorEnabled, ErrorPageEnabled, PluginsEnabled, - FullScreenSupportEnabled + FullScreenSupportEnabled, + ScreenCaptureEnabled, + WebGLEnabled, + WebAudioEnabled, + Accelerated2dCanvasEnabled }; enum FontSize { diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp index 362849732..e066f2d0e 100644 --- a/src/webenginewidgets/api/qwebengineview.cpp +++ b/src/webenginewidgets/api/qwebengineview.cpp @@ -122,6 +122,7 @@ QWebEngineView::QWebEngineView(QWidget *parent) { Q_D(QWebEngineView); d->q_ptr = this; + setAcceptDrops(true); // This causes the child RenderWidgetHostViewQtDelegateWidgets to fill this widget. setLayout(new QStackedLayout); @@ -312,6 +313,40 @@ void QWebEngineView::hideEvent(QHideEvent *event) page()->d_ptr->wasHidden(); } +void QWebEngineView::dragEnterEvent(QDragEnterEvent *e) +{ + Q_D(QWebEngineView); + e->accept(); + d->page->d_ptr->adapter->enterDrag(e, mapToGlobal(e->pos())); +} + +void QWebEngineView::dragLeaveEvent(QDragLeaveEvent *e) +{ + Q_D(QWebEngineView); + e->accept(); + d->page->d_ptr->adapter->leaveDrag(); +} + +void QWebEngineView::dragMoveEvent(QDragMoveEvent *e) +{ + Q_D(QWebEngineView); + QtWebEngineCore::WebContentsAdapter *adapter = d->page->d_ptr->adapter.data(); + Qt::DropAction dropAction = adapter->updateDragPosition(e, mapToGlobal(e->pos())); + if (Qt::IgnoreAction == dropAction) { + e->ignore(); + } else { + e->setDropAction(dropAction); + e->accept(); + } +} + +void QWebEngineView::dropEvent(QDropEvent *e) +{ + Q_D(QWebEngineView); + e->accept(); + d->page->d_ptr->adapter->endDragging(e->pos(), mapToGlobal(e->pos())); +} + #ifndef QT_NO_ACCESSIBILITY int QWebEngineViewAccessible::childCount() const { diff --git a/src/webenginewidgets/api/qwebengineview.h b/src/webenginewidgets/api/qwebengineview.h index e16bbf4af..432813395 100644 --- a/src/webenginewidgets/api/qwebengineview.h +++ b/src/webenginewidgets/api/qwebengineview.h @@ -122,6 +122,10 @@ protected: virtual bool event(QEvent*) Q_DECL_OVERRIDE; virtual void showEvent(QShowEvent *) Q_DECL_OVERRIDE; virtual void hideEvent(QHideEvent *) Q_DECL_OVERRIDE; + void dragEnterEvent(QDragEnterEvent *e) Q_DECL_OVERRIDE; + void dragLeaveEvent(QDragLeaveEvent *e) Q_DECL_OVERRIDE; + void dragMoveEvent(QDragMoveEvent *e) Q_DECL_OVERRIDE; + void dropEvent(QDropEvent *e) Q_DECL_OVERRIDE; private: Q_DISABLE_COPY(QWebEngineView) diff --git a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc index a6f015434..e09561bef 100644 --- a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc @@ -122,6 +122,9 @@ \value RequestClose Request to close the web page. If defined, the \c{window.onbeforeunload} handler is run, and the user can confirm or reject to close the page. If the close request is confirmed, \c windowCloseRequested is emitted. (Added in Qt 5.6) + \value Unselect Clear the current selection. (Added in Qt 5.7) + \value SavePage Save the current page to disk. MHTML is the default format that is used to store + the web page on disk. (Added in Qt 5.7) \omitvalue WebActionCount @@ -687,3 +690,37 @@ \sa iconUrl() */ + +/*! + \property QWebEnginePage::audioMuted + \brief the state of whether the current page audio is muted. + \since 5.7 +*/ + +/*! + \fn void QWebEnginePage::audioMutedChanged(bool muted) + \since 5.7 + + This signal is emitted when the page's audio is (un)muted using setAudioMuted method. + \note Not to be confused with a specific HTML5 audio / video element being muted. +*/ + +/*! + \fn bool QWebEnginePage::wasRecentlyAudible() + \since 5.7 + \sa wasRecentlyAudibleChanged() + + Returns the current page's audible state (audio was recently played, or not). +*/ + +/*! + \fn void QWebEnginePage::wasRecentlyAudibleChanged(bool wasRecentlyAudible); + \since 5.7 + + This signal is emitted when the page's audible state is changed, due to audio + being played or stopped. + + \note The signal is also emitted when calling the setAudioMuted method. + Also if the audio is paused, this signal is emitted with an approximate \b{2 second + delay}, from the moment the audio is paused. +*/ diff --git a/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc index 3dc23e037..6b518a1f2 100644 --- a/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc @@ -66,6 +66,8 @@ \value SansSerifFont \value CursiveFont \value FantasyFont + \value PictographFont + (added in Qt 5.7) */ /*! @@ -123,6 +125,15 @@ Enables support for Pepper plugins, such as the Flash player. Disabled by default. \value FullScreenSupportEnabled Enables fullscreen support in an application. Disabled by default. + \value ScreenCaptureEnabled + Enables screen capture in an application. Disabled by default. + \value WebGLEnabled + Enables support for HTML 5 WebGL. Enabled by default if available. + \value WebAudioEnabled + Enables support for HTML 5 WebAudio. Disabled by default. + \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. */ /*! diff --git a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp index 09929d33f..d24a43b41 100644 --- a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp +++ b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp @@ -37,6 +37,7 @@ #include "../util.h" #include <QtTest/QtTest> #include <qwebengineprofile.h> +#include <qwebenginepage.h> class tst_QWebEngineProfile : public QObject { @@ -45,6 +46,7 @@ class tst_QWebEngineProfile : public QObject private Q_SLOTS: void defaultProfile(); void profileConstructors(); + void clearDataFromCache(); }; void tst_QWebEngineProfile::defaultProfile() @@ -69,7 +71,45 @@ void tst_QWebEngineProfile::profileConstructors() QCOMPARE(diskProfile.httpCacheType(), QWebEngineProfile::DiskHttpCache); QCOMPARE(otrProfile.persistentCookiesPolicy(), QWebEngineProfile::NoPersistentCookies); QCOMPARE(diskProfile.persistentCookiesPolicy(), QWebEngineProfile::AllowPersistentCookies); +} + +void tst_QWebEngineProfile::clearDataFromCache() +{ + QWebEnginePage page; + + QDir cacheDir("./tst_QWebEngineProfile_cacheDir"); + cacheDir.makeAbsolute(); + if (cacheDir.exists()) + cacheDir.removeRecursively(); + cacheDir.mkpath(cacheDir.path()); + + QWebEngineProfile *profile = page.profile(); + profile->setCachePath(cacheDir.path()); + profile->setHttpCacheType(QWebEngineProfile::DiskHttpCache); + + QSignalSpy loadFinishedSpy(&page, SIGNAL(loadFinished(bool))); + page.load(QUrl("http://qt-project.org")); + if (!loadFinishedSpy.wait(10000) || !loadFinishedSpy.at(0).at(0).toBool()) + QSKIP("Couldn't load page from network, skipping test."); + + cacheDir.refresh(); + QVERIFY(cacheDir.entryList().contains("Cache")); + cacheDir.cd("./Cache"); + int filesBeforeClear = cacheDir.entryList().count(); + + QFileSystemWatcher fileSystemWatcher; + fileSystemWatcher.addPath(cacheDir.path()); + QSignalSpy directoryChangedSpy(&fileSystemWatcher, SIGNAL(directoryChanged(const QString &))); + + // It deletes most of the files, but not all of them. + profile->clearHttpCache(); + QTest::qWait(1000); + QTRY_VERIFY(directoryChangedSpy.count() > 0); + + cacheDir.refresh(); + QVERIFY(filesBeforeClear > cacheDir.entryList().count()); + cacheDir.removeRecursively(); } QTEST_MAIN(tst_QWebEngineProfile) diff --git a/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp b/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp index 53762f54c..3231293bf 100644 --- a/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp +++ b/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp @@ -115,12 +115,14 @@ void tst_QWebEngineScript::scriptWorld() page.load(QUrl("about:blank")); waitForSignal(&page, SIGNAL(loadFinished(bool))); QCOMPARE(evaluateJavaScriptSync(&page, "typeof(userScriptTest) != \"undefined\" && userScriptTest == 1;"), QVariant::fromValue(true)); + QCOMPARE(evaluateJavaScriptSyncInWorld(&page, "typeof(userScriptTest) == \"undefined\"", QWebEngineScript::ApplicationWorld), QVariant::fromValue(true)); script.setWorldId(QWebEngineScript::ApplicationWorld); page.scripts().clear(); page.scripts().insert(script); page.load(QUrl("about:blank")); waitForSignal(&page, SIGNAL(loadFinished(bool))); QCOMPARE(evaluateJavaScriptSync(&page, "typeof(userScriptTest) == \"undefined\""), QVariant::fromValue(true)); + QCOMPARE(evaluateJavaScriptSyncInWorld(&page, "typeof(userScriptTest) != \"undefined\" && userScriptTest == 1;", QWebEngineScript::ApplicationWorld), QVariant::fromValue(true)); } void tst_QWebEngineScript::scriptModifications() diff --git a/tests/auto/widgets/util.h b/tests/auto/widgets/util.h index 2b485fc0f..c2c72c8f4 100644 --- a/tests/auto/widgets/util.h +++ b/tests/auto/widgets/util.h @@ -156,6 +156,13 @@ static inline QVariant evaluateJavaScriptSync(QWebEnginePage *page, const QStrin return spy.waitForResult(); } +static inline QVariant evaluateJavaScriptSyncInWorld(QWebEnginePage *page, const QString &script, int worldId) +{ + CallbackSpy<QVariant> spy; + page->runJavaScript(script, worldId, spy.ref()); + return spy.waitForResult(); +} + static inline QUrl baseUrlSync(QWebEnginePage *page) { CallbackSpy<QVariant> spy; diff --git a/tools/buildscripts/gyp_qtwebengine b/tools/buildscripts/gyp_qtwebengine index c8e849973..ec24caeb1 100755 --- a/tools/buildscripts/gyp_qtwebengine +++ b/tools/buildscripts/gyp_qtwebengine @@ -122,16 +122,15 @@ if __name__ == '__main__': args.extend(['-D', 'host_arch=x64', '-D', 'use_libcpp=1']) # There shouldn't be a circular dependency relationship between .gyp files, - # but in Chromium's .gyp files, on non-Mac platforms, circular relationships + # but in Chromium's .gyp files, on non-iOS platforms, circular relationships # currently exist. The check for circular dependencies is currently - # bypassed on other platforms, but is left enabled on the Mac, where a - # violation of the rule causes Xcode to misbehave badly. + # bypassed on other platforms, but is left enabled on iOS, where a violation + # of the rule causes Xcode to misbehave badly. # TODO(mark): Find and kill remaining circular dependencies, and remove this # option. http://crbug.com/35878. # TODO(tc): Fix circular dependencies in ChromiumOS then add linux2 to the # list. - if sys.platform not in ('darwin',) or 'GYP_CROSSCOMPILE' in os.environ: - args.append('--no-circular-check') + args.append('--no-circular-check') # libtool on Mac warns about duplicate basenames in static libraries, so # they're disallowed in general by gyp. We are lax on this point, so disable diff --git a/tools/buildscripts/repack_locales.py b/tools/buildscripts/repack_locales.py index 3d974c93a..102129680 100755 --- a/tools/buildscripts/repack_locales.py +++ b/tools/buildscripts/repack_locales.py @@ -59,6 +59,9 @@ chrome_src = utils.getChromiumSrcDir() sys.path.append(os.path.join(chrome_src, 'tools', 'grit')) from grit.format import data_pack +# The gyp "branding" variable. +BRANDING = 'chromium' + # Some build paths defined by gyp. SHARE_INT_DIR = None INT_DIR = None @@ -84,6 +87,19 @@ def calc_inputs(locale): """Determine the files that need processing for the given locale.""" inputs = [] + #e.g. '<(SHARED_INTERMEDIATE_DIR)/components/strings/ + # components_strings_da.pak', + inputs.append(os.path.join(SHARE_INT_DIR, 'components', 'strings', + 'components_strings_%s.pak' % locale)) + + #e.g. '<(SHARED_INTERMEDIATE_DIR)/components/strings/ + # components_chromium_strings_da.pak' + # or + # '<(SHARED_INTERMEDIATE_DIR)/components/strings/ + # components_google_chrome_strings_da.pak', + inputs.append(os.path.join(SHARE_INT_DIR, 'components', 'strings', + 'components_%s_strings_%s.pak' % (BRANDING, locale))) + if OS != 'ios': #e.g. '<(SHARED_INTERMEDIATE_DIR)/content/app/strings/content_strings_en-US.pak' inputs.append(os.path.join(SHARE_INT_DIR, 'content', 'app', 'strings', diff --git a/tools/qmake/config.tests/libvpx/libvpx.cpp b/tools/qmake/config.tests/libvpx/libvpx.cpp new file mode 100644 index 000000000..640341e8b --- /dev/null +++ b/tools/qmake/config.tests/libvpx/libvpx.cpp @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <vpx/svc_context.h> +#include <vpx/vpx_frame_buffer.h> + +int main(int, char **) +{ + return 0; +} diff --git a/tools/qmake/config.tests/libvpx/libvpx.pro b/tools/qmake/config.tests/libvpx/libvpx.pro new file mode 100644 index 000000000..aff6d1857 --- /dev/null +++ b/tools/qmake/config.tests/libvpx/libvpx.pro @@ -0,0 +1,3 @@ +SOURCES += libvpx.cpp +PKGCONFIG += libvpx +CONFIG -= qt diff --git a/tools/qmake/mkspecs/features/configure.prf b/tools/qmake/mkspecs/features/configure.prf index 4be9fac20..07fd56d5d 100644 --- a/tools/qmake/mkspecs/features/configure.prf +++ b/tools/qmake/mkspecs/features/configure.prf @@ -41,12 +41,12 @@ defineTest(runConfigure) { else: log("System libwebp or libwebpdemux not found. Using Chromium's copies.$${EOL}") packagesExist(libxml-2.0,libxslt): WEBENGINE_CONFIG += use_system_libxslt else: log("System libxml2 or libxslt not found. Using Chromium's copies.$${EOL}") - for(package, $$list("libevent flac jsoncpp opus speex")) { + for(package, $$list("libevent flac jsoncpp opus")) { packagesExist($$package): WEBENGINE_CONFIG += use_system_$$package else: log("System $$package not found. Using Chromium's copy.$${EOL}") } - packagesExist("\'vpx >= 1.4\'"): WEBENGINE_CONFIG += use_system_vpx - else: log("System vpx >= 1.4 not found. Using Chromium's copy.$${EOL}") + config_libvpx: WEBENGINE_CONFIG += use_system_vpx + else: log("Compatible system libvpx not found. Using Chromium's copy.$${EOL}") config_srtp: WEBENGINE_CONFIG += use_system_libsrtp else: log("System libsrtp not found. Using Chromium's copy.$${EOL}") config_snappy: WEBENGINE_CONFIG += use_system_snappy diff --git a/tools/scripts/take_snapshot.py b/tools/scripts/take_snapshot.py index 5f911f36f..ea0c73328 100755 --- a/tools/scripts/take_snapshot.py +++ b/tools/scripts/take_snapshot.py @@ -103,6 +103,8 @@ def isInChromiumBlacklist(file_path): not 'media/desktop_streams_registry.' in file_path and not 'common/chrome_switches.' in file_path and not 'common/localized_error.' in file_path and + not 'common/spellcheck_' in file_path and + not '/spellchecker/' in file_path and not file_path.endswith('cf_resources.rc') and not file_path.endswith('version.py') and not file_path.endswith('.grd') and @@ -113,18 +115,25 @@ def isInChromiumBlacklist(file_path): or file_path.startswith('chromeos') or file_path.startswith('cloud_print') or (file_path.startswith('components') and + not file_path.startswith('components/cdm') and not file_path.startswith('components/device_event_log') and not file_path.startswith('components/devtools_') and not file_path.startswith('components/error_page') and + not file_path.startswith('components/keyed_service') and not file_path.startswith('components/mime_util') and + not file_path.startswith('components/pref_registry') and not file_path.startswith('components/printing') and not file_path.startswith('components/resources') and not file_path.startswith('components/scheduler') and + not file_path.startswith('components/security_interstitials') and not file_path.startswith('components/strings') and not file_path.startswith('components/tracing') and + not file_path.startswith('components/url_formatter') and + not file_path.startswith('components/user_prefs') and not file_path.startswith('components/visitedlink') and not file_path.startswith('components/web_cache') and not file_path.startswith('components/webcrypto') and + not file_path.endswith('.grd') and not file_path.endswith('.grdp') and not 'components_strings' in file_path) or file_path.startswith('content/public/android/java') @@ -157,6 +166,7 @@ def isInChromiumBlacklist(file_path): or file_path.startswith('third_party/bison') or (file_path.startswith('third_party/cacheinvalidation') and not file_path.endswith('isolate')) + or file_path.startswith('third_party/catapult') or file_path.startswith('third_party/chromite') or file_path.startswith('third_party/cld_2') or file_path.startswith('third_party/codesighs') @@ -173,7 +183,6 @@ def isInChromiumBlacklist(file_path): or file_path.startswith('third_party/google_appengine_cloudstorage') or file_path.startswith('third_party/google_toolbox_for_mac') or file_path.startswith('third_party/hunspell_dictionaries') - or file_path.startswith('third_party/hunspell') or file_path.startswith('third_party/instrumented_libraries') or file_path.startswith('third_party/jsr-305/src') or file_path.startswith('third_party/junit') @@ -194,6 +203,7 @@ def isInChromiumBlacklist(file_path): or file_path.startswith('third_party/pdfium') or file_path.startswith('third_party/psyco_win32') or file_path.startswith('third_party/scons-2.0.1') + or file_path.startswith('third_party/sfntly/src/cpp/data/fonts') or file_path.startswith('third_party/trace-viewer') or file_path.startswith('third_party/undoview') or file_path.startswith('third_party/webgl') diff --git a/tools/scripts/version_resolver.py b/tools/scripts/version_resolver.py index a4fafe83e..c63e3e381 100644 --- a/tools/scripts/version_resolver.py +++ b/tools/scripts/version_resolver.py @@ -51,8 +51,8 @@ import json import urllib2 import git_submodule as GitSubmodule -chromium_version = '45.0.2454.101' -chromium_branch = '2454' +chromium_version = '47.0.2526.109' +chromium_branch = '2526' ninja_version = 'v1.6.0' json_url = 'http://omahaproxy.appspot.com/all.json' |