summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2016-05-10 16:58:00 +0200
committerAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2016-05-10 16:58:12 +0200
commite5157941181f6bb5e906377e68af9bbe2ab55795 (patch)
treee0f109b51e8faa44cb36ca2ac95d8cd1b4387be2
parentc2f7f09974959c252a5e2879adfffe6356543fff (diff)
parent023168cf91dc7ac11ced1b6a60ca7aa248987810 (diff)
Merge remote-tracking branch 'origin/5.7' into dev
-rw-r--r--examples/webenginewidgets/demobrowser/browserapplication.cpp29
-rw-r--r--examples/webenginewidgets/demobrowser/browserapplication.h1
-rw-r--r--examples/webenginewidgets/demobrowser/edittreeview.cpp7
-rw-r--r--examples/webenginewidgets/demobrowser/history.cpp99
-rw-r--r--examples/webenginewidgets/demobrowser/history.h13
-rw-r--r--examples/webenginewidgets/demobrowser/tabwidget.cpp3
-rw-r--r--examples/webenginewidgets/simplebrowser/webview.cpp7
m---------src/3rdparty0
-rw-r--r--src/core/api/qtwebenginecoreglobal.cpp2
-rw-r--r--src/core/browser_context_adapter.cpp11
-rw-r--r--src/core/browser_context_qt.cpp29
-rw-r--r--src/core/browser_context_qt.h2
-rw-r--r--src/core/core_gyp_generator.pro1
-rw-r--r--src/core/favicon_manager.cpp109
-rw-r--r--src/core/favicon_manager.h9
-rw-r--r--src/core/favicon_manager_p.h2
-rw-r--r--src/core/gyp_run.pro3
-rw-r--r--src/core/network_delegate_qt.cpp3
-rw-r--r--src/core/qtwebengine.gypi2
-rw-r--r--src/core/qtwebengine_extras.gypi22
-rw-r--r--src/core/url_request_context_getter_qt.cpp171
-rw-r--r--src/core/url_request_context_getter_qt.h39
-rw-r--r--src/core/web_contents_adapter.cpp1
-rw-r--r--src/core/web_engine_library_info.cpp18
-rw-r--r--src/process/process.pro2
-rw-r--r--src/src.pro7
-rw-r--r--src/tools/qwebengine_convert_dict/main.cpp183
-rw-r--r--src/tools/qwebengine_convert_dict/qwebengine_convert_dict.pro22
-rw-r--r--src/webengine/api/qquickwebenginecontextmenudata.cpp30
-rw-r--r--src/webengine/api/qquickwebenginecontextmenudata_p.h7
-rw-r--r--src/webengine/api/qquickwebenginefaviconprovider.cpp7
-rw-r--r--src/webengine/api/qquickwebengineprofile.cpp89
-rw-r--r--src/webengine/api/qquickwebengineprofile.h10
-rw-r--r--src/webengine/api/qquickwebengineview.cpp17
-rw-r--r--src/webengine/api/qquickwebengineview_p.h2
-rw-r--r--src/webengine/doc/src/qtwebengine-platform-notes.qdoc60
-rw-r--r--src/webengine/doc/src/webengineview.qdoc25
-rw-r--r--src/webenginewidgets/api/qwebenginecontextmenudata.cpp20
-rw-r--r--src/webenginewidgets/api/qwebenginecontextmenudata.h2
-rw-r--r--src/webenginewidgets/api/qwebenginepage.cpp36
-rw-r--r--src/webenginewidgets/api/qwebenginepage.h2
-rw-r--r--src/webenginewidgets/api/qwebengineprofile.cpp62
-rw-r--r--src/webenginewidgets/api/qwebengineprofile.h6
-rw-r--r--src/webenginewidgets/api/qwebengineview.cpp1
-rw-r--r--tests/auto/quick/qmltests/data/favicon-candidates-gray.html29
-rw-r--r--tests/auto/quick/qmltests/data/favicon-multi-gray.html16
-rw-r--r--tests/auto/quick/qmltests/data/icons/gray128.pngbin0 -> 146 bytes
-rw-r--r--tests/auto/quick/qmltests/data/icons/gray16.pngbin0 -> 72 bytes
-rw-r--r--tests/auto/quick/qmltests/data/icons/gray255.pngbin0 -> 335 bytes
-rw-r--r--tests/auto/quick/qmltests/data/icons/gray32.pngbin0 -> 79 bytes
-rw-r--r--tests/auto/quick/qmltests/data/icons/gray64.pngbin0 -> 99 bytes
-rw-r--r--tests/auto/quick/qmltests/data/tst_favicon.qml33
-rw-r--r--tests/auto/quick/qmltests/qmltests.pro6
-rw-r--r--tests/auto/widgets/qwebenginefaviconmanager/tst_qwebenginefaviconmanager.cpp38
-rw-r--r--tests/auto/widgets/qwebenginespellcheck/dict/en-US.aff5
-rw-r--r--tests/auto/widgets/qwebenginespellcheck/dict/en-US.dic11
-rw-r--r--tests/auto/widgets/qwebenginespellcheck/qwebenginespellcheck.pro22
-rw-r--r--tests/auto/widgets/qwebenginespellcheck/resources/index.html36
-rw-r--r--tests/auto/widgets/qwebenginespellcheck/tst_qwebenginespellcheck.cpp178
-rw-r--r--tests/auto/widgets/qwebenginespellcheck/tst_qwebenginespellcheck.qrc5
-rw-r--r--tests/auto/widgets/widgets.pro5
-rw-r--r--tools/qmake/mkspecs/features/configure.prf4
-rw-r--r--tools/qmake/mkspecs/features/default_pre.prf12
63 files changed, 1076 insertions, 497 deletions
diff --git a/examples/webenginewidgets/demobrowser/browserapplication.cpp b/examples/webenginewidgets/demobrowser/browserapplication.cpp
index 0d5c54199..26764b93c 100644
--- a/examples/webenginewidgets/demobrowser/browserapplication.cpp
+++ b/examples/webenginewidgets/demobrowser/browserapplication.cpp
@@ -136,11 +136,7 @@ BrowserApplication::BrowserApplication(int &argc, char **argv)
socket.connectToServer(serverName);
if (socket.waitForConnected(500)) {
QTextStream stream(&socket);
- QStringList args = QCoreApplication::arguments();
- if (args.count() > 1)
- stream << args.last();
- else
- stream << QString();
+ stream << getCommandLineUrlArgument();
stream.flush();
socket.waitForBytesWritten();
return;
@@ -255,11 +251,13 @@ void BrowserApplication::postLaunch()
// newMainWindow() needs to be called in main() for this to happen
if (m_mainWindows.count() > 0) {
- QStringList args = QCoreApplication::arguments();
- if (args.count() > 1)
- mainWindow()->loadPage(args.last());
- else
+ const QString url = getCommandLineUrlArgument();
+ if (!url.isEmpty()) {
+ mainWindow()->loadPage(url);
+ } else {
mainWindow()->slotHome();
+ }
+
}
BrowserApplication::historyManager();
}
@@ -421,6 +419,19 @@ void BrowserApplication::installTranslator(const QString &name)
QApplication::installTranslator(translator);
}
+QString BrowserApplication::getCommandLineUrlArgument() const
+{
+ const QStringList args = QCoreApplication::arguments();
+ if (args.count() > 1) {
+ const QString lastArg = args.last();
+ const bool isValidUrl = QUrl::fromUserInput(lastArg).isValid();
+ if (isValidUrl)
+ return lastArg;
+ }
+
+ return QString();
+}
+
#if defined(Q_OS_OSX)
bool BrowserApplication::event(QEvent* event)
{
diff --git a/examples/webenginewidgets/demobrowser/browserapplication.h b/examples/webenginewidgets/demobrowser/browserapplication.h
index f509c67f7..5c75d41b3 100644
--- a/examples/webenginewidgets/demobrowser/browserapplication.h
+++ b/examples/webenginewidgets/demobrowser/browserapplication.h
@@ -119,6 +119,7 @@ private slots:
private:
void clean();
void installTranslator(const QString &name);
+ QString getCommandLineUrlArgument() const;
static HistoryManager *s_historyManager;
static DownloadManager *s_downloadManager;
diff --git a/examples/webenginewidgets/demobrowser/edittreeview.cpp b/examples/webenginewidgets/demobrowser/edittreeview.cpp
index 763fbec5c..f4c9a0d70 100644
--- a/examples/webenginewidgets/demobrowser/edittreeview.cpp
+++ b/examples/webenginewidgets/demobrowser/edittreeview.cpp
@@ -49,6 +49,8 @@
****************************************************************************/
#include "edittreeview.h"
+#include "browserapplication.h"
+#include "history.h"
#include <QtGui/QKeyEvent>
@@ -73,13 +75,12 @@ void EditTreeView::removeOne()
if (!model())
return;
QModelIndex ci = currentIndex();
- int row = ci.row();
- model()->removeRow(row, ci.parent());
+ BrowserApplication::historyManager()->removeHistoryEntry(model()->data(ci,HistoryModel::UrlStringRole).toString());
}
void EditTreeView::removeAll()
{
if (!model())
return;
- model()->removeRows(0, model()->rowCount(rootIndex()), rootIndex());
+ BrowserApplication::historyManager()->clear();
}
diff --git a/examples/webenginewidgets/demobrowser/history.cpp b/examples/webenginewidgets/demobrowser/history.cpp
index aaab44ac8..188490aca 100644
--- a/examples/webenginewidgets/demobrowser/history.cpp
+++ b/examples/webenginewidgets/demobrowser/history.cpp
@@ -101,7 +101,7 @@ HistoryManager::~HistoryManager()
m_saveTimer->saveIfNeccessary();
}
-QList<HistoryItem> HistoryManager::history() const
+QList<HistoryItem> &HistoryManager::history()
{
return m_history;
}
@@ -120,6 +120,15 @@ void HistoryManager::addHistoryEntry(const QString &url)
addHistoryItem(item);
}
+void HistoryManager::removeHistoryEntry(const QString &url)
+{
+ QUrl cleanUrl(url);
+ cleanUrl.setPassword(QString());
+ cleanUrl.setHost(cleanUrl.host().toLower());
+ HistoryItem item(cleanUrl.toString(), QDateTime::currentDateTime());
+ removeHistoryItem(item);
+}
+
void HistoryManager::setHistory(const QList<HistoryItem> &history, bool loadedAndSorted)
{
m_history = history;
@@ -173,7 +182,7 @@ void HistoryManager::checkForExpired()
}
if (nextTimeout > 0)
break;
- HistoryItem item = m_history.takeLast();
+ const HistoryItem& item = m_history.last();
// remove from saved file also
m_lastSavedUrl = QString();
emit entryRemoved(item);
@@ -188,12 +197,21 @@ void HistoryManager::addHistoryItem(const HistoryItem &item)
if (BrowserApplication::instance()->privateBrowsing())
return;
- m_history.prepend(item);
emit entryAdded(item);
if (m_history.count() == 1)
checkForExpired();
}
+void HistoryManager::removeHistoryItem(const HistoryItem &item)
+{
+ for (int i = m_history.count() - 1 ; i >= 0; --i) {
+ if (item.url == m_history.at(i).url) {
+ //delete all related entries with that url
+ emit entryRemoved(m_history.at(i));
+ }
+ }
+}
+
void HistoryManager::updateHistoryItem(const QUrl &url, const QString &title)
{
for (int i = 0; i < m_history.count(); ++i) {
@@ -224,7 +242,6 @@ void HistoryManager::setHistoryLimit(int limit)
void HistoryManager::clear()
{
- m_history.clear();
m_lastSavedUrl = QString();
emit historyReset();
m_saveTimer->changeOccurred();
@@ -374,10 +391,10 @@ HistoryModel::HistoryModel(HistoryManager *history, QObject *parent)
connect(m_history, SIGNAL(historyReset()),
this, SLOT(historyReset()));
connect(m_history, SIGNAL(entryRemoved(HistoryItem)),
- this, SLOT(historyReset()));
+ this, SLOT(entryRemoved(HistoryItem)));
connect(m_history, SIGNAL(entryAdded(HistoryItem)),
- this, SLOT(entryAdded()));
+ this, SLOT(entryAdded(HistoryItem)));
connect(m_history, SIGNAL(entryUpdated(int)),
this, SLOT(entryUpdated(int)));
}
@@ -385,15 +402,26 @@ HistoryModel::HistoryModel(HistoryManager *history, QObject *parent)
void HistoryModel::historyReset()
{
beginResetModel();
+ m_history->history().clear();
endResetModel();
}
-void HistoryModel::entryAdded()
+void HistoryModel::entryAdded(const HistoryItem &item)
{
beginInsertRows(QModelIndex(), 0, 0);
+ m_history->history().prepend(item);
endInsertRows();
}
+void HistoryModel::entryRemoved(const HistoryItem &item)
+{
+ int index = m_history->history().indexOf(item);
+ Q_ASSERT(index > -1);
+ beginRemoveRows(QModelIndex(),index, index);
+ m_history->history().takeAt(index);
+ endRemoveRows();
+}
+
void HistoryModel::entryUpdated(int offset)
{
QModelIndex idx = index(offset, 0);
@@ -468,12 +496,9 @@ bool HistoryModel::removeRows(int row, int count, const QModelIndex &parent)
return false;
int lastRow = row + count - 1;
beginRemoveRows(parent, row, lastRow);
- QList<HistoryItem> lst = m_history->history();
+ QList<HistoryItem> &lst = m_history->history();
for (int i = lastRow; i >= row; --i)
lst.removeAt(i);
- disconnect(m_history, SIGNAL(historyReset()), this, SLOT(historyReset()));
- m_history->setHistory(lst);
- connect(m_history, SIGNAL(historyReset()), this, SLOT(historyReset()));
endRemoveRows();
return true;
}
@@ -664,8 +689,6 @@ TreeProxyModel::TreeProxyModel(QObject *parent) : QSortFilterProxyModel(parent)
bool TreeProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
- if (!source_parent.isValid())
- return true;
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
}
@@ -678,14 +701,16 @@ HistoryDialog::HistoryDialog(QWidget *parent, HistoryManager *setHistory) : QDia
tree->setUniformRowHeights(true);
tree->setSelectionBehavior(QAbstractItemView::SelectRows);
tree->setTextElideMode(Qt::ElideMiddle);
- QAbstractItemModel *model = history->historyTreeModel();
+ QAbstractItemModel *model = history->historyFilterModel();
TreeProxyModel *proxyModel = new TreeProxyModel(this);
connect(search, SIGNAL(textChanged(QString)),
proxyModel, SLOT(setFilterFixedString(QString)));
connect(removeButton, SIGNAL(clicked()), tree, SLOT(removeOne()));
- connect(removeAllButton, SIGNAL(clicked()), history, SLOT(clear()));
+ connect(removeAllButton, SIGNAL(clicked()), tree, SLOT(removeAll()));
proxyModel->setSourceModel(model);
+ proxyModel->setFilterKeyColumn(1);
tree->setModel(proxyModel);
+ tree->setSortingEnabled(true);
tree->setExpanded(proxyModel->index(0, 0), true);
tree->setAlternatingRowColors(true);
QFontMetrics fm(font());
@@ -739,25 +764,13 @@ HistoryFilterModel::HistoryFilterModel(QAbstractItemModel *sourceModel, QObject
setSourceModel(sourceModel);
}
-int HistoryFilterModel::historyLocation(const QString &url) const
-{
- load();
- if (!m_historyHash.contains(url))
- return 0;
- return sourceModel()->rowCount() - m_historyHash.value(url);
-}
-
-QVariant HistoryFilterModel::data(const QModelIndex &index, int role) const
-{
- return QAbstractProxyModel::data(index, role);
-}
-
void HistoryFilterModel::setSourceModel(QAbstractItemModel *newSourceModel)
{
+ beginResetModel();
if (sourceModel()) {
disconnect(sourceModel(), SIGNAL(modelReset()), this, SLOT(sourceReset()));
disconnect(sourceModel(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
- this, SLOT(dataChanged(QModelIndex,QModelIndex)));
+ this, SLOT(sourceDataChanged(QModelIndex,QModelIndex)));
disconnect(sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
this, SLOT(sourceRowsInserted(QModelIndex,int,int)));
disconnect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)),
@@ -767,7 +780,6 @@ void HistoryFilterModel::setSourceModel(QAbstractItemModel *newSourceModel)
QAbstractProxyModel::setSourceModel(newSourceModel);
if (sourceModel()) {
- m_loaded = false;
connect(sourceModel(), SIGNAL(modelReset()), this, SLOT(sourceReset()));
connect(sourceModel(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
this, SLOT(sourceDataChanged(QModelIndex,QModelIndex)));
@@ -776,6 +788,8 @@ void HistoryFilterModel::setSourceModel(QAbstractItemModel *newSourceModel)
connect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)),
this, SLOT(sourceRowsRemoved(QModelIndex,int,int)));
}
+ load();
+ endResetModel();
}
void HistoryFilterModel::sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
@@ -790,14 +804,13 @@ QVariant HistoryFilterModel::headerData(int section, Qt::Orientation orientation
void HistoryFilterModel::sourceReset()
{
- m_loaded = false;
beginResetModel();
+ load();
endResetModel();
}
int HistoryFilterModel::rowCount(const QModelIndex &parent) const
{
- load();
if (parent.isValid())
return 0;
return m_historyHash.count();
@@ -810,14 +823,12 @@ int HistoryFilterModel::columnCount(const QModelIndex &parent) const
QModelIndex HistoryFilterModel::mapToSource(const QModelIndex &proxyIndex) const
{
- load();
int sourceRow = sourceModel()->rowCount() - proxyIndex.internalId();
return sourceModel()->index(sourceRow, proxyIndex.column());
}
QModelIndex HistoryFilterModel::mapFromSource(const QModelIndex &sourceIndex) const
{
- load();
QString url = sourceIndex.data(HistoryModel::UrlStringRole).toString();
if (!m_historyHash.contains(url))
return QModelIndex();
@@ -843,7 +854,6 @@ QModelIndex HistoryFilterModel::mapFromSource(const QModelIndex &sourceIndex) co
QModelIndex HistoryFilterModel::index(int row, int column, const QModelIndex &parent) const
{
- load();
if (row < 0 || row >= rowCount(parent)
|| column < 0 || column >= columnCount(parent))
return QModelIndex();
@@ -858,8 +868,6 @@ QModelIndex HistoryFilterModel::parent(const QModelIndex &) const
void HistoryFilterModel::load() const
{
- if (m_loaded)
- return;
m_sourceRow.clear();
m_historyHash.clear();
m_historyHash.reserve(sourceModel()->rowCount());
@@ -871,15 +879,12 @@ void HistoryFilterModel::load() const
m_historyHash[url] = sourceModel()->rowCount() - i;
}
}
- m_loaded = true;
}
void HistoryFilterModel::sourceRowsInserted(const QModelIndex &parent, int start, int end)
{
Q_ASSERT(start == end && start == 0);
Q_UNUSED(end);
- if (!m_loaded)
- return;
QModelIndex idx = sourceModel()->index(start, 0, parent);
QString url = idx.data(HistoryModel::UrlStringRole).toString();
if (m_historyHash.contains(url)) {
@@ -1184,6 +1189,7 @@ bool HistoryTreeModel::removeRows(int row, int count, const QModelIndex &parent)
void HistoryTreeModel::setSourceModel(QAbstractItemModel *newSourceModel)
{
+ beginResetModel();
if (sourceModel()) {
disconnect(sourceModel(), SIGNAL(modelReset()), this, SLOT(sourceReset()));
disconnect(sourceModel(), SIGNAL(layoutChanged()), this, SLOT(sourceReset()));
@@ -1191,6 +1197,8 @@ void HistoryTreeModel::setSourceModel(QAbstractItemModel *newSourceModel)
this, SLOT(sourceRowsInserted(QModelIndex,int,int)));
disconnect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)),
this, SLOT(sourceRowsRemoved(QModelIndex,int,int)));
+ disconnect(sourceModel(), &QAbstractItemModel::dataChanged, this,
+ &HistoryTreeModel::sourceDataChanged);
}
QAbstractProxyModel::setSourceModel(newSourceModel);
@@ -1202,9 +1210,9 @@ void HistoryTreeModel::setSourceModel(QAbstractItemModel *newSourceModel)
this, SLOT(sourceRowsInserted(QModelIndex,int,int)));
connect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)),
this, SLOT(sourceRowsRemoved(QModelIndex,int,int)));
+ connect(sourceModel(), &QAbstractItemModel::dataChanged, this,
+ &HistoryTreeModel::sourceDataChanged);
}
-
- beginResetModel();
endResetModel();
}
@@ -1293,3 +1301,10 @@ void HistoryTreeModel::sourceRowsRemoved(const QModelIndex &parent, int start, i
endRemoveRows();
}
}
+
+void HistoryTreeModel::sourceDataChanged(const QModelIndex &topLeft,
+ const QModelIndex &bottomRight,
+ const QVector<int> roles)
+{
+ emit dataChanged(mapFromSource(topLeft), mapFromSource(bottomRight), roles);
+}
diff --git a/examples/webenginewidgets/demobrowser/history.h b/examples/webenginewidgets/demobrowser/history.h
index 0ae5a7bf7..6d7da5e6d 100644
--- a/examples/webenginewidgets/demobrowser/history.h
+++ b/examples/webenginewidgets/demobrowser/history.h
@@ -103,14 +103,16 @@ public:
~HistoryManager();
bool historyContains(const QString &url) const;
+
void addHistoryEntry(const QString &url);
+ void removeHistoryEntry(const QString &url);
void updateHistoryItem(const QUrl &url, const QString &title);
int historyLimit() const;
void setHistoryLimit(int limit);
- QList<HistoryItem> history() const;
+ QList<HistoryItem>& history();
void setHistory(const QList<HistoryItem> &history, bool loadedAndSorted = false);
// History manager keeps around these models for use by the completer and other classes
@@ -128,6 +130,7 @@ private slots:
protected:
void addHistoryItem(const HistoryItem &item);
+ void removeHistoryItem(const HistoryItem &item);
private:
void load();
@@ -149,7 +152,8 @@ class HistoryModel : public QAbstractTableModel
public slots:
void historyReset();
- void entryAdded();
+ void entryAdded(const HistoryItem &item);
+ void entryRemoved(const HistoryItem &item);
void entryUpdated(int offset);
public:
@@ -185,7 +189,6 @@ public:
inline bool historyContains(const QString &url) const
{ load(); return m_historyHash.contains(url); }
- int historyLocation(const QString &url) const;
QModelIndex mapFromSource(const QModelIndex &sourceIndex) const;
QModelIndex mapToSource(const QModelIndex &proxyIndex) const;
@@ -196,7 +199,6 @@ public:
QModelIndex index(int, int, const QModelIndex& = QModelIndex()) const;
QModelIndex parent(const QModelIndex& index= QModelIndex()) const;
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
private slots:
void sourceReset();
@@ -314,7 +316,8 @@ private slots:
void sourceReset();
void sourceRowsInserted(const QModelIndex &parent, int start, int end);
void sourceRowsRemoved(const QModelIndex &parent, int start, int end);
-
+ void sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
+ const QVector<int> roles);
private:
int sourceDateRow(int row) const;
mutable QList<int> m_sourceRowCache;
diff --git a/examples/webenginewidgets/demobrowser/tabwidget.cpp b/examples/webenginewidgets/demobrowser/tabwidget.cpp
index 3b56d115b..e684d3757 100644
--- a/examples/webenginewidgets/demobrowser/tabwidget.cpp
+++ b/examples/webenginewidgets/demobrowser/tabwidget.cpp
@@ -782,6 +782,9 @@ void TabWidget::webViewUrlChanged(const QUrl &url)
int index = webViewIndex(webView);
if (-1 != index) {
m_tabBar->setTabData(index, url);
+ HistoryManager *manager = BrowserApplication::historyManager();
+ if (url.isValid())
+ manager->addHistoryEntry(url.toString());
}
emit tabsChanged();
}
diff --git a/examples/webenginewidgets/simplebrowser/webview.cpp b/examples/webenginewidgets/simplebrowser/webview.cpp
index 24835b10b..9a5a75092 100644
--- a/examples/webenginewidgets/simplebrowser/webview.cpp
+++ b/examples/webenginewidgets/simplebrowser/webview.cpp
@@ -79,8 +79,11 @@ WebView::WebView(QWidget *parent)
status = tr("Render process killed");
break;
}
- QMessageBox::critical(window(), status, tr("Render process exited with code: %1").arg(statusCode));
- QTimer::singleShot(0, [this] { reload(); });
+ QMessageBox::StandardButton btn = QMessageBox::question(window(), status,
+ tr("Render process exited with code: %1\n"
+ "Do you want to reload the page ?").arg(statusCode));
+ if (btn == QMessageBox::Yes)
+ QTimer::singleShot(0, [this] { reload(); });
});
}
diff --git a/src/3rdparty b/src/3rdparty
-Subproject ba40ed24a6d23e606397b650a7982b0998dbeaf
+Subproject 46f522d613bb77600ed3a85580ff84ee9802e21
diff --git a/src/core/api/qtwebenginecoreglobal.cpp b/src/core/api/qtwebenginecoreglobal.cpp
index 8f004777f..f5d1e6d39 100644
--- a/src/core/api/qtwebenginecoreglobal.cpp
+++ b/src/core/api/qtwebenginecoreglobal.cpp
@@ -79,9 +79,11 @@ QWEBENGINE_PRIVATE_EXPORT void initialize()
return;
}
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 1))
// Bail out silently if the user did not construct a QGuiApplication.
if (!qobject_cast<QGuiApplication *>(app))
return;
+#endif
if (app->thread() != QThread::currentThread()) {
qFatal("QtWebEngine::initialize() must be called from the Qt gui thread.");
diff --git a/src/core/browser_context_adapter.cpp b/src/core/browser_context_adapter.cpp
index e0f933562..ba9d671ae 100644
--- a/src/core/browser_context_adapter.cpp
+++ b/src/core/browser_context_adapter.cpp
@@ -151,6 +151,8 @@ QWebEngineUrlRequestInterceptor *BrowserContextAdapter::requestInterceptor()
void BrowserContextAdapter::setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor)
{
m_requestInterceptor = interceptor;
+ if (m_browserContext->url_request_getter_.get())
+ m_browserContext->url_request_getter_->updateRequestInterceptor();
}
void BrowserContextAdapter::addClient(BrowserContextAdapterClient *adapterClient)
@@ -466,15 +468,6 @@ void BrowserContextAdapter::clearHttpCache()
m_browserContext->url_request_getter_->clearHttpCache();
}
-QStringList BrowserContextAdapter::spellCheckLanguages(const QStringList &acceptLanguages)
-{
-#if defined(ENABLE_SPELLCHECK)
- return m_browserContext->spellCheckLanguages(acceptLanguages);
-#else
- return QStringList();
-#endif
-}
-
void BrowserContextAdapter::setSpellCheckLanguage(const QString &language)
{
#if defined(ENABLE_SPELLCHECK)
diff --git a/src/core/browser_context_qt.cpp b/src/core/browser_context_qt.cpp
index 5b3115530..1c326fb83 100644
--- a/src/core/browser_context_qt.cpp
+++ b/src/core/browser_context_qt.cpp
@@ -47,6 +47,7 @@
#include "ssl_host_state_delegate_qt.h"
#include "type_conversion.h"
#include "url_request_context_getter_qt.h"
+#include "web_engine_library_info.h"
#include "base/time/time.h"
#include "content/public/browser/browser_thread.h"
@@ -54,6 +55,7 @@
#include "net/proxy/proxy_config_service.h"
#if defined(ENABLE_SPELLCHECK)
+#include "base/base_paths.h"
#include "base/prefs/pref_member.h"
#include "base/prefs/pref_service.h"
#include "base/prefs/testing_pref_store.h"
@@ -78,12 +80,9 @@ BrowserContextQt::BrowserContextQt(BrowserContextAdapter *adapter)
scoped_refptr<PrefRegistrySimple> registry(new PrefRegistrySimple());
// Initial spellcheck settings
- std::string spellcheckLang = QLocale().bcp47Name().toStdString();
- base::ListValue *dictionaries = new base::ListValue;
- dictionaries->AppendString(spellcheckLang);
- registry->RegisterListPref(prefs::kSpellCheckDictionaries, dictionaries);
- registry->RegisterStringPref(prefs::kAcceptLanguages, spellcheckLang);
- registry->RegisterStringPref(prefs::kSpellCheckDictionary, spellcheckLang);
+ registry->RegisterListPref(prefs::kSpellCheckDictionaries, new base::ListValue());
+ registry->RegisterStringPref(prefs::kAcceptLanguages, std::string());
+ registry->RegisterStringPref(prefs::kSpellCheckDictionary, std::string());
registry->RegisterBooleanPref(prefs::kSpellCheckUseSpellingService, false);
registry->RegisterBooleanPref(prefs::kEnableContinuousSpellcheck, false);
registry->RegisterBooleanPref(prefs::kEnableAutoSpellCorrect, false);
@@ -201,22 +200,12 @@ net::URLRequestContextGetter *BrowserContextQt::CreateRequestContext(content::Pr
return url_request_getter_.get();
}
-
#if defined(ENABLE_SPELLCHECK)
-QStringList BrowserContextQt::spellCheckLanguages(const QStringList& acceptedLanguages)
+void BrowserContextQt::failedToLoadDictionary(const std::string &language)
{
- QStringList result;
-#if !defined(OS_MACOSX) // no SpellcheckService::GetSpellCheckLanguages
- m_prefService->SetString(prefs::kAcceptLanguages,acceptedLanguages.join(",").toStdString());
-
- std::vector<std::string> vec;
- SpellcheckService::GetSpellCheckLanguages(this, &vec);
-
- for (std::vector<std::string>::iterator it = vec.begin(); it != vec.end(); ++it) {
- result << QString::fromStdString(*it);
- }
-#endif
- return result;
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ qWarning() << "Could not load dictionary for:" << toQt(language) << endl
+ << "Make sure that correct bdic file is in:" << toQt(WebEngineLibraryInfo::getPath(base::DIR_APP_DICTIONARIES).value());
}
void BrowserContextQt::setSpellCheckLanguage(const QString &language)
diff --git a/src/core/browser_context_qt.h b/src/core/browser_context_qt.h
index 08ac05fd4..e2156f147 100644
--- a/src/core/browser_context_qt.h
+++ b/src/core/browser_context_qt.h
@@ -92,7 +92,7 @@ public:
BrowserContextAdapter *adapter() { return m_adapter; }
#if defined(ENABLE_SPELLCHECK)
- QStringList spellCheckLanguages(const QStringList &acceptLanguages);
+ void failedToLoadDictionary(const std::string& language) override;
void setSpellCheckLanguage(const QString &language);
QString spellCheckLanguage() const;
void setSpellCheckEnabled(bool enabled);
diff --git a/src/core/core_gyp_generator.pro b/src/core/core_gyp_generator.pro
index 09df6b48d..3e6a9eac0 100644
--- a/src/core/core_gyp_generator.pro
+++ b/src/core/core_gyp_generator.pro
@@ -13,7 +13,6 @@ include(core_common.pri)
DEFINES += QT_NO_KEYWORDS \
QT_USE_QSTRINGBUILDER \
Q_FORWARD_DECLARE_OBJC_CLASS=QT_FORWARD_DECLARE_CLASS \
- QTWEBENGINEPROCESS_NAME=\\\"$$QTWEBENGINEPROCESS_NAME\\\" \
QTWEBENGINECORE_VERSION_STR=\\\"$$MODULE_VERSION\\\" \
BUILDING_CHROMIUM
diff --git a/src/core/favicon_manager.cpp b/src/core/favicon_manager.cpp
index 5568e6eb5..be8d17725 100644
--- a/src/core/favicon_manager.cpp
+++ b/src/core/favicon_manager.cpp
@@ -52,9 +52,6 @@
#include "third_party/skia/include/core/SkPixelRef.h"
#include "ui/gfx/geometry/size.h"
-#include <QtCore/QUrl>
-#include <QtGui/QIcon>
-
namespace QtWebEngineCore {
static inline bool isResourceUrl(const QUrl &url)
@@ -139,6 +136,11 @@ void FaviconManagerPrivate::downloadPendingRequests()
void FaviconManagerPrivate::storeIcon(int id, const QIcon &icon)
{
Q_Q(FaviconManager);
+
+ // Icon download has been interrupted
+ if (m_inProgressRequests.isEmpty())
+ return;
+
Q_ASSERT(m_inProgressRequests.contains(id));
QUrl requestUrl = m_inProgressRequests[id];
@@ -169,31 +171,18 @@ void FaviconManagerPrivate::storeIcon(int id, const QIcon &icon)
}
m_inProgressRequests.remove(id);
- if (m_inProgressRequests.isEmpty())
- propagateIcon();
-}
-
-void FaviconManagerPrivate::propagateIcon() const
-{
- Q_Q(const FaviconManager);
+ if (m_inProgressRequests.isEmpty()) {
+ WebEngineSettings *settings = m_viewClient->webEngineSettings();
+ bool touchIconsEnabled = settings->testAttribute(WebEngineSettings::TouchIconsEnabled);
- WebEngineSettings *settings = m_viewClient->webEngineSettings();
- bool touchIconsEnabled = settings->testAttribute(WebEngineSettings::TouchIconsEnabled);
-
- QUrl iconUrl;
- const QList<FaviconInfo> &faviconInfoList = q->getFaviconInfoList(true /* candidates only */);
-
- unsigned bestArea = 0;
- for (auto it = faviconInfoList.cbegin(), end = faviconInfoList.cend(); it != end; ++it) {
- if (!touchIconsEnabled && it->type != FaviconInfo::Favicon)
- continue;
-
- if (it->isValid() && bestArea < area(it->size)) {
- iconUrl = it->url;
- bestArea = area(it->size);
- }
+ q->generateCandidateIcon(touchIconsEnabled);
+ const QUrl &iconUrl = q->candidateIconUrl(touchIconsEnabled);
+ propagateIcon(iconUrl);
}
+}
+void FaviconManagerPrivate::propagateIcon(const QUrl &iconUrl) const
+{
content::NavigationEntry *entry = m_webContents->GetController().GetVisibleEntry();
if (entry) {
content::FaviconStatus &favicon = entry->GetFavicon();
@@ -205,7 +194,7 @@ void FaviconManagerPrivate::propagateIcon() const
}
FaviconManager::FaviconManager(FaviconManagerPrivate *d)
- : m_hasCandidate(false)
+ : m_candidateCount(0)
{
Q_ASSERT(d);
d_ptr.reset(d);
@@ -220,6 +209,10 @@ FaviconManager::~FaviconManager()
QIcon FaviconManager::getIcon(const QUrl &url) const
{
Q_D(const FaviconManager);
+
+ if (url.isEmpty())
+ return m_candidateIcon;
+
if (!d->m_icons.contains(url))
return QIcon();
@@ -281,7 +274,7 @@ void FaviconManager::update(const QList<FaviconInfo> &candidates)
void FaviconManager::updateCandidates(const QList<FaviconInfo> &candidates)
{
- m_hasCandidate = candidates.count();
+ m_candidateCount = candidates.count();
for (FaviconInfo candidateFaviconInfo : candidates) {
const QUrl &candidateUrl = candidateFaviconInfo.url;
@@ -298,14 +291,71 @@ void FaviconManager::updateCandidates(const QList<FaviconInfo> &candidates)
void FaviconManager::resetCandidates()
{
- m_hasCandidate = false;
+ Q_D(FaviconManager);
+
+ // Interrupt in progress icon downloads
+ d->m_pendingRequests.clear();
+ d->m_inProgressRequests.clear();
+
+ m_candidateCount = 0;
+ m_candidateIcon = QIcon();
for (auto it = m_faviconInfoMap.begin(), end = m_faviconInfoMap.end(); it != end; ++it)
it->candidate = false;
}
bool FaviconManager::hasCandidate() const
{
- return m_hasCandidate;
+ return (m_candidateCount > 0);
+}
+
+QUrl FaviconManager::candidateIconUrl(bool touchIconsEnabled) const
+{
+ QUrl iconUrl;
+ const QList<FaviconInfo> &faviconInfoList = getFaviconInfoList(true /* candidates only */);
+
+ unsigned bestArea = 0;
+ for (auto it = faviconInfoList.cbegin(), end = faviconInfoList.cend(); it != end; ++it) {
+ if (!touchIconsEnabled && it->type != FaviconInfo::Favicon)
+ continue;
+
+ if (it->isValid() && bestArea < area(it->size)) {
+ iconUrl = it->url;
+ bestArea = area(it->size);
+ }
+ }
+
+ return iconUrl;
+}
+
+void FaviconManager::generateCandidateIcon(bool touchIconsEnabled)
+{
+ Q_ASSERT(m_candidateCount);
+
+ m_candidateIcon = QIcon();
+ const QList<FaviconInfo> &faviconInfoList = getFaviconInfoList(true /* candidates only */);
+
+ for (auto it = faviconInfoList.cbegin(), end = faviconInfoList.cend(); it != end; ++it) {
+ if (!touchIconsEnabled && it->type != FaviconInfo::Favicon)
+ continue;
+
+ if (!it->isValid() || !it->isDownloaded())
+ continue;
+
+ const QIcon &icon = getIcon(it->url);
+
+ if (!it->multiSize) {
+ if (!m_candidateIcon.availableSizes().contains(it->size))
+ m_candidateIcon.addPixmap(icon.pixmap(it->size));
+
+ continue;
+ }
+
+ const auto sizes = icon.availableSizes();
+ for (const QSize &size : sizes) {
+ if (!m_candidateIcon.availableSizes().contains(size))
+ m_candidateIcon.addPixmap(icon.pixmap(size));
+ }
+ }
}
@@ -323,6 +373,7 @@ FaviconInfo::FaviconInfo(const FaviconInfo &other)
, type(other.type)
, size(other.size)
, candidate(other.candidate)
+ , multiSize(other.multiSize)
{
}
diff --git a/src/core/favicon_manager.h b/src/core/favicon_manager.h
index dc702a0da..e351831c2 100644
--- a/src/core/favicon_manager.h
+++ b/src/core/favicon_manager.h
@@ -46,6 +46,7 @@
#include <QtCore/QObject>
#include <QtCore/QSize>
#include <QtCore/QUrl>
+#include <QtGui/QIcon>
#include "web_engine_settings.h"
@@ -85,7 +86,7 @@ class QWEBENGINE_EXPORT FaviconManager : public QObject {
public:
~FaviconManager();
- QIcon getIcon(const QUrl &) const;
+ QIcon getIcon(const QUrl &url = QUrl()) const;
FaviconInfo getFaviconInfo(const QUrl &) const;
QList<FaviconInfo> getFaviconInfoList(bool) const;
@@ -97,8 +98,12 @@ private:
void resetCandidates();
bool hasCandidate() const;
+ QUrl candidateIconUrl(bool touchIconsEnabled) const;
+ void generateCandidateIcon(bool touchIconsEnabled);
+
QMap<QUrl, FaviconInfo> m_faviconInfoMap;
- bool m_hasCandidate;
+ int m_candidateCount;
+ QIcon m_candidateIcon;
Q_DISABLE_COPY(FaviconManager)
Q_DECLARE_PRIVATE(FaviconManager)
diff --git a/src/core/favicon_manager_p.h b/src/core/favicon_manager_p.h
index 80a012474..e2a49dbc7 100644
--- a/src/core/favicon_manager_p.h
+++ b/src/core/favicon_manager_p.h
@@ -87,7 +87,7 @@ public:
void iconDownloadFinished(int, int, const GURL &, const std::vector<SkBitmap> &, const std::vector<gfx::Size> &);
void storeIcon(int, const QIcon &);
void downloadPendingRequests();
- void propagateIcon() const;
+ void propagateIcon(const QUrl &) const;
content::WebContents *m_webContents;
WebContentsAdapterClient *m_viewClient;
diff --git a/src/core/gyp_run.pro b/src/core/gyp_run.pro
index f7fca8fa8..2e2422dce 100644
--- a/src/core/gyp_run.pro
+++ b/src/core/gyp_run.pro
@@ -16,7 +16,8 @@ cross_compile {
mac: include(config/mac_osx.pri)
win32: include(config/windows.pri)
}
-
+GYP_CONFIG += qtwe_process_name_debug=$$QTWEBENGINEPROCESS_NAME_DEBUG
+GYP_CONFIG += qtwe_process_name_release=$$QTWEBENGINEPROCESS_NAME_RELEASE
GYP_CONFIG += disable_glibcxx_debug=1
!webcore_debug: GYP_CONFIG += remove_webcore_debug_symbols=1
!v8base_debug: GYP_CONFIG += remove_v8base_debug_symbols=1
diff --git a/src/core/network_delegate_qt.cpp b/src/core/network_delegate_qt.cpp
index b1a2faf8d..ff0e8320c 100644
--- a/src/core/network_delegate_qt.cpp
+++ b/src/core/network_delegate_qt.cpp
@@ -90,7 +90,6 @@ int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, const net::C
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
Q_ASSERT(m_requestContextGetter);
- Q_ASSERT(m_requestContextGetter->m_browserContext);
const content::ResourceRequestInfo *resourceInfo = content::ResourceRequestInfo::ForRequest(request);
@@ -104,7 +103,7 @@ int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, const net::C
const QUrl qUrl = toQt(request->url());
- QWebEngineUrlRequestInterceptor* interceptor = m_requestContextGetter->m_browserContext->requestInterceptor();
+ QWebEngineUrlRequestInterceptor* interceptor = m_requestContextGetter->m_requestInterceptor;
if (interceptor) {
QWebEngineUrlRequestInfoPrivate *infoPrivate = new QWebEngineUrlRequestInfoPrivate(static_cast<QWebEngineUrlRequestInfo::ResourceType>(resourceType)
, static_cast<QWebEngineUrlRequestInfo::NavigationType>(navigationType)
diff --git a/src/core/qtwebengine.gypi b/src/core/qtwebengine.gypi
index 7ed12cadb..4077431b1 100644
--- a/src/core/qtwebengine.gypi
+++ b/src/core/qtwebengine.gypi
@@ -8,7 +8,7 @@
'dependencies': [
'<(chromium_src_dir)/base/base.gyp:base',
'<(chromium_src_dir)/base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
- '<(chromium_src_dir)/chrome/tools/convert_dict/convert_dict.gyp:convert_dict',
+ '<(chromium_src_dir)/chrome/tools/convert_dict/convert_dict.gyp:convert_dict_lib',
'<(chromium_src_dir)/components/components.gyp:devtools_discovery',
'<(chromium_src_dir)/components/components.gyp:devtools_http_handler',
'<(chromium_src_dir)/components/components.gyp:error_page_renderer',
diff --git a/src/core/qtwebengine_extras.gypi b/src/core/qtwebengine_extras.gypi
index a5de08b55..229421efa 100644
--- a/src/core/qtwebengine_extras.gypi
+++ b/src/core/qtwebengine_extras.gypi
@@ -63,6 +63,28 @@
'defines': [
'TOOLKIT_QT',
],
+ 'configurations': {
+ 'Debug': {
+ 'defines': [
+ 'QTWEBENGINEPROCESS_NAME="<(qtwe_process_name_debug)"'
+ ],
+ },
+ 'Debug_x64': {
+ 'defines': [
+ 'QTWEBENGINEPROCESS_NAME="<(qtwe_process_name_debug)"'
+ ],
+ },
+ 'Release': {
+ 'defines': [
+ 'QTWEBENGINEPROCESS_NAME="<(qtwe_process_name_release)"'
+ ],
+ },
+ 'Release_x64': {
+ 'defines': [
+ 'QTWEBENGINEPROCESS_NAME="<(qtwe_process_name_release)"'
+ ],
+ },
+ },
},
'conditions': [
[ 'qt_os=="embedded_linux"', {
diff --git a/src/core/url_request_context_getter_qt.cpp b/src/core/url_request_context_getter_qt.cpp
index afbb66b95..579e33b66 100644
--- a/src/core/url_request_context_getter_qt.cpp
+++ b/src/core/url_request_context_getter_qt.cpp
@@ -91,14 +91,23 @@ using content::BrowserThread;
URLRequestContextGetterQt::URLRequestContextGetterQt(QSharedPointer<BrowserContextAdapter> browserContext, content::ProtocolHandlerMap *protocolHandlers, content::URLRequestInterceptorScopedVector request_interceptors)
: m_ignoreCertificateErrors(false)
+ , m_mutex(QMutex::Recursive)
+ , m_contextInitialized(false)
+ , m_updateAllStorage(false)
+ , m_updateCookieStore(false)
+ , m_updateHttpCache(false)
+ , m_updateJobFactory(true)
+ , m_updateUserAgent(false)
, m_browserContext(browserContext)
, m_baseJobFactory(0)
, m_cookieDelegate(new CookieMonsterDelegateQt())
, m_requestInterceptors(std::move(request_interceptors))
{
std::swap(m_protocolHandlers, *protocolHandlers);
- m_cookieDelegate->setClient(m_browserContext->cookieStore());
+ QMutexLocker lock(&m_mutex);
+ m_cookieDelegate->setClient(browserContext->cookieStore());
+ setFullConfiguration(browserContext);
updateStorageSettings();
}
@@ -108,6 +117,23 @@ URLRequestContextGetterQt::~URLRequestContextGetterQt()
delete m_proxyConfigService.fetchAndStoreAcquire(0);
}
+
+void URLRequestContextGetterQt::setFullConfiguration(QSharedPointer<BrowserContextAdapter> browserContext)
+{
+ if (!browserContext)
+ return;
+
+ m_requestInterceptor = browserContext->requestInterceptor();
+ m_persistentCookiesPolicy = browserContext->persistentCookiesPolicy();
+ m_cookiesPath = browserContext->cookiesPath();
+ m_httpAcceptLanguage = browserContext->httpAcceptLanguage();
+ m_httpUserAgent = browserContext->httpUserAgent();
+ m_httpCacheType = browserContext->httpCacheType();
+ m_httpCachePath = browserContext->httpCachePath();
+ m_httpCacheMaxSize = browserContext->httpCacheMaxSize();
+ m_customUrlSchemes = browserContext->customUrlSchemes();
+}
+
net::URLRequestContext *URLRequestContextGetterQt::GetURLRequestContext()
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
@@ -117,8 +143,10 @@ net::URLRequestContext *URLRequestContextGetterQt::GetURLRequestContext()
m_networkDelegate.reset(new NetworkDelegateQt(this));
m_urlRequestContext->set_network_delegate(m_networkDelegate.get());
- generateStorage();
+ QMutexLocker lock(&m_mutex);
+ generateAllStorage();
generateJobFactory();
+ m_contextInitialized = true;
}
return m_urlRequestContext.get();
@@ -127,24 +155,31 @@ net::URLRequestContext *URLRequestContextGetterQt::GetURLRequestContext()
void URLRequestContextGetterQt::updateStorageSettings()
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- // m_proxyConfigService having a non-null value is used to indicate
- // storage is already being updated.
- if (!m_proxyConfigService.loadAcquire()) {
+
+ QMutexLocker lock(&m_mutex);
+ setFullConfiguration(m_browserContext.toStrongRef());
+
+ if (!m_updateAllStorage) {
+ m_updateAllStorage = true;
// We must create the proxy config service on the UI loop on Linux because it
// must synchronously run on the glib message loop. This will be passed to
// the URLRequestContextStorage on the IO thread in GetURLRequestContext().
- m_proxyConfigService.storeRelease(new ProxyConfigServiceQt(net::ProxyService::CreateSystemProxyConfigService(
- content::BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
- content::BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)
- )));
- if (m_storage) {
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestContextGetterQt::generateStorage, this));
- }
+ Q_ASSERT(m_proxyConfigService == 0);
+ m_proxyConfigService =
+ new ProxyConfigServiceQt(
+ net::ProxyService::CreateSystemProxyConfigService(
+ content::BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
+ content::BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)
+ ));
+ if (m_contextInitialized)
+ content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&URLRequestContextGetterQt::generateAllStorage, this));
}
}
void URLRequestContextGetterQt::cancelAllUrlRequests()
{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
Q_ASSERT(m_urlRequestContext);
std::set<const net::URLRequest*>* url_requests = m_urlRequestContext->url_requests();
@@ -158,6 +193,17 @@ void URLRequestContextGetterQt::cancelAllUrlRequests()
}
+void URLRequestContextGetterQt::generateAllStorage()
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ QMutexLocker lock(&m_mutex);
+ generateStorage();
+ generateCookieStore();
+ generateUserAgent();
+ generateHttpCache();
+ m_updateAllStorage = false;
+}
+
void URLRequestContextGetterQt::generateStorage()
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
@@ -175,8 +221,6 @@ void URLRequestContextGetterQt::generateStorage()
net::ProxyConfigService *proxyConfigService = m_proxyConfigService.fetchAndStoreAcquire(0);
Q_ASSERT(proxyConfigService);
- generateCookieStore();
- generateUserAgent();
m_storage->set_channel_id_service(scoped_ptr<net::ChannelIDService>(new net::ChannelIDService(
new net::DefaultChannelIDStore(NULL),
@@ -207,16 +251,20 @@ void URLRequestContextGetterQt::generateStorage()
// Give |m_storage| ownership at the end in case it's |mapped_host_resolver|.
m_storage->set_host_resolver(std::move(host_resolver));
-
- generateHttpCache();
}
void URLRequestContextGetterQt::updateCookieStore()
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- // Do not trigger an update if another is already triggered, or we are not yet initialized.
- if (m_urlRequestContext && !m_proxyConfigService && !m_updateCookieStore.fetchAndStoreRelaxed(1))
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestContextGetterQt::generateCookieStore, this));
+ QMutexLocker lock(&m_mutex);
+ m_httpAcceptLanguage = m_browserContext.data()->httpAcceptLanguage();
+ m_httpUserAgent = m_browserContext.data()->httpUserAgent();
+
+ if (m_contextInitialized && !m_updateAllStorage && !m_updateCookieStore) {
+ m_updateCookieStore = true;
+ content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&URLRequestContextGetterQt::generateCookieStore, this));
+ }
}
void URLRequestContextGetterQt::generateCookieStore()
@@ -224,14 +272,16 @@ void URLRequestContextGetterQt::generateCookieStore()
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
Q_ASSERT(m_urlRequestContext);
Q_ASSERT(m_storage);
- m_updateCookieStore = 0;
+
+ QMutexLocker lock(&m_mutex);
+ m_updateCookieStore = false;
// Unset it first to get a chance to destroy and flush the old cookie store before opening a new on possibly the same file.
m_storage->set_cookie_store(0);
m_cookieDelegate->setCookieMonster(0);
net::CookieStore* cookieStore = 0;
- switch (m_browserContext->persistentCookiesPolicy()) {
+ switch (m_persistentCookiesPolicy) {
case BrowserContextAdapter::NoPersistentCookies:
cookieStore =
content::CreateCookieStore(content::CookieStoreConfig(
@@ -244,7 +294,7 @@ void URLRequestContextGetterQt::generateCookieStore()
case BrowserContextAdapter::AllowPersistentCookies:
cookieStore =
content::CreateCookieStore(content::CookieStoreConfig(
- toFilePath(m_browserContext->cookiesPath()),
+ toFilePath(m_cookiesPath),
content::CookieStoreConfig::PERSISTANT_SESSION_COOKIES,
NULL,
m_cookieDelegate.get())
@@ -253,7 +303,7 @@ void URLRequestContextGetterQt::generateCookieStore()
case BrowserContextAdapter::ForcePersistentCookies:
cookieStore =
content::CreateCookieStore(content::CookieStoreConfig(
- toFilePath(m_browserContext->cookiesPath()),
+ toFilePath(m_cookiesPath),
content::CookieStoreConfig::RESTORED_SESSION_COOKIES,
NULL,
m_cookieDelegate.get())
@@ -270,9 +320,15 @@ void URLRequestContextGetterQt::generateCookieStore()
void URLRequestContextGetterQt::updateUserAgent()
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- // Do not trigger an update if all storage settings are already being updated
- if (m_urlRequestContext && !m_proxyConfigService)
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestContextGetterQt::generateUserAgent, this));
+ QMutexLocker lock(&m_mutex);
+ m_httpAcceptLanguage = m_browserContext.data()->httpAcceptLanguage();
+ m_httpUserAgent = m_browserContext.data()->httpUserAgent();
+
+ if (m_contextInitialized && !m_updateAllStorage && !m_updateUserAgent) {
+ m_updateUserAgent = true;
+ content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&URLRequestContextGetterQt::generateUserAgent, this));
+ }
}
void URLRequestContextGetterQt::generateUserAgent()
@@ -281,26 +337,48 @@ void URLRequestContextGetterQt::generateUserAgent()
Q_ASSERT(m_urlRequestContext);
Q_ASSERT(m_storage);
+ QMutexLocker lock(&m_mutex);
+ m_updateUserAgent = true;
+
m_storage->set_http_user_agent_settings(scoped_ptr<net::HttpUserAgentSettings>(
- new net::StaticHttpUserAgentSettings(m_browserContext->httpAcceptLanguage().toStdString(), m_browserContext->httpUserAgent().toStdString())));
+ new net::StaticHttpUserAgentSettings(m_httpAcceptLanguage.toStdString(), m_httpUserAgent.toStdString())));
}
void URLRequestContextGetterQt::updateHttpCache()
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- // Do not trigger a new update if another is already triggered
- if (m_urlRequestContext && !m_proxyConfigService && !m_updateHttpCache.fetchAndStoreRelaxed(1))
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestContextGetterQt::generateHttpCache, this));
+ QMutexLocker lock(&m_mutex);
+ m_httpCacheType = m_browserContext.data()->httpCacheType();
+ m_httpCachePath = m_browserContext.data()->httpCachePath();
+ m_httpCacheMaxSize = m_browserContext.data()->httpCacheMaxSize();
+
+ if (m_contextInitialized && !m_updateAllStorage && !m_updateHttpCache) {
+ m_updateHttpCache = true;
+ content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&URLRequestContextGetterQt::generateHttpCache, this));
+ }
}
void URLRequestContextGetterQt::updateJobFactory()
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ QMutexLocker lock(&m_mutex);
+ m_customUrlSchemes = m_browserContext.data()->customUrlSchemes();
- if (m_urlRequestContext && !m_updateJobFactory.fetchAndStoreRelaxed(1))
+ if (m_contextInitialized && !m_updateJobFactory) {
+ m_updateJobFactory = true;
content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
- base::Bind(&URLRequestContextGetterQt::regenerateJobFactory,
- this, m_browserContext->customUrlSchemes()));
+ base::Bind(&URLRequestContextGetterQt::regenerateJobFactory, this));
+ }
+}
+
+void URLRequestContextGetterQt::updateRequestInterceptor()
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ QMutexLocker lock(&m_mutex);
+ m_requestInterceptor = m_browserContext.data()->requestInterceptor();
+
+ // We in this case do not need to regenerate any Chromium classes.
}
static bool doNetworkSessionParamsMatch(const net::HttpNetworkSession::Params &first, const net::HttpNetworkSession::Params &second)
@@ -355,15 +433,18 @@ void URLRequestContextGetterQt::generateHttpCache()
Q_ASSERT(m_urlRequestContext);
Q_ASSERT(m_storage);
+ QMutexLocker lock(&m_mutex);
+ m_updateHttpCache = false;
+
net::HttpCache::DefaultBackend* main_backend = 0;
- switch (m_browserContext->httpCacheType()) {
+ switch (m_httpCacheType) {
case BrowserContextAdapter::MemoryHttpCache:
main_backend =
new net::HttpCache::DefaultBackend(
net::MEMORY_CACHE,
net::CACHE_BACKEND_DEFAULT,
base::FilePath(),
- m_browserContext->httpCacheMaxSize(),
+ m_httpCacheMaxSize,
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE)
);
break;
@@ -372,8 +453,8 @@ void URLRequestContextGetterQt::generateHttpCache()
new net::HttpCache::DefaultBackend(
net::DISK_CACHE,
net::CACHE_BACKEND_DEFAULT,
- toFilePath(m_browserContext->httpCachePath()),
- m_browserContext->httpCacheMaxSize(),
+ toFilePath(m_httpCachePath),
+ m_httpCacheMaxSize,
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE)
);
break;
@@ -393,7 +474,6 @@ void URLRequestContextGetterQt::generateHttpCache()
cache = new net::HttpCache(m_httpNetworkSession.get(), scoped_ptr<net::HttpCache::DefaultBackend>(main_backend), false);
m_storage->set_http_transaction_factory(scoped_ptr<net::HttpCache>(cache));
- m_updateHttpCache = 0;
}
void URLRequestContextGetterQt::clearHttpCache()
@@ -419,6 +499,9 @@ void URLRequestContextGetterQt::generateJobFactory()
Q_ASSERT(m_urlRequestContext);
Q_ASSERT(!m_jobFactory);
+ QMutexLocker lock(&m_mutex);
+ m_updateJobFactory = false;
+
scoped_ptr<net::URLRequestJobFactoryImpl> jobFactory(new net::URLRequestJobFactoryImpl());
{
@@ -437,7 +520,7 @@ void URLRequestContextGetterQt::generateJobFactory()
jobFactory->SetProtocolHandler(url::kFtpScheme,
scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(new net::FtpProtocolHandler(new net::FtpNetworkLayer(m_urlRequestContext->host_resolver()))));
- m_installedCustomSchemes = m_browserContext->customUrlSchemes();
+ m_installedCustomSchemes = m_customUrlSchemes;
Q_FOREACH (const QByteArray &scheme, m_installedCustomSchemes) {
jobFactory->SetProtocolHandler(scheme.toStdString(), scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(new CustomProtocolHandler(m_browserContext)));
}
@@ -457,22 +540,24 @@ void URLRequestContextGetterQt::generateJobFactory()
m_urlRequestContext->set_job_factory(m_jobFactory.get());
}
-void URLRequestContextGetterQt::regenerateJobFactory(const QList<QByteArray> customSchemes)
+void URLRequestContextGetterQt::regenerateJobFactory()
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
Q_ASSERT(m_urlRequestContext);
Q_ASSERT(m_jobFactory);
Q_ASSERT(m_baseJobFactory);
- m_updateJobFactory.storeRelease(0);
- if (customSchemes == m_installedCustomSchemes)
+ QMutexLocker lock(&m_mutex);
+ m_updateJobFactory = false;
+
+ if (m_customUrlSchemes == m_installedCustomSchemes)
return;
Q_FOREACH (const QByteArray &scheme, m_installedCustomSchemes) {
m_baseJobFactory->SetProtocolHandler(scheme.toStdString(), nullptr);
}
- m_installedCustomSchemes = customSchemes;
+ m_installedCustomSchemes = m_customUrlSchemes;
Q_FOREACH (const QByteArray &scheme, m_installedCustomSchemes) {
m_baseJobFactory->SetProtocolHandler(scheme.toStdString(), scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(new CustomProtocolHandler(m_browserContext)));
}
diff --git a/src/core/url_request_context_getter_qt.h b/src/core/url_request_context_getter_qt.h
index 7078c7a44..eca956ea6 100644
--- a/src/core/url_request_context_getter_qt.h
+++ b/src/core/url_request_context_getter_qt.h
@@ -55,9 +55,10 @@
#include "cookie_monster_delegate_qt.h"
#include "network_delegate_qt.h"
+#include "browser_context_adapter.h"
-#include <QtCore/qglobal.h>
#include <QtCore/qatomic.h>
+#include <QtCore/qmutex.h>
#include <QtCore/qsharedpointer.h>
namespace net {
@@ -67,8 +68,7 @@ class ProxyConfigService;
namespace QtWebEngineCore {
-class BrowserContextAdapter;
-
+// FIXME: This class should be split into a URLRequestContextGetter and a ProfileIOData, similar to what chrome does.
class URLRequestContextGetterQt : public net::URLRequestContextGetter {
public:
URLRequestContextGetterQt(QSharedPointer<BrowserContextAdapter> browserContext, content::ProtocolHandlerMap *protocolHandlers, content::URLRequestInterceptorScopedVector request_interceptors);
@@ -83,26 +83,36 @@ public:
void updateHttpCache();
void clearHttpCache();
void updateJobFactory();
+ void updateRequestInterceptor();
private:
virtual ~URLRequestContextGetterQt();
// Called on the IO thread:
+ void generateAllStorage();
void generateStorage();
void generateCookieStore();
void generateHttpCache();
void generateUserAgent();
void generateJobFactory();
- void regenerateJobFactory(const QList<QByteArray> customSchemes);
+ void regenerateJobFactory();
void clearCurrentCacheBackend();
void cancelAllUrlRequests();
net::HttpNetworkSession::Params generateNetworkSessionParams();
+ void setFullConfiguration(QSharedPointer<BrowserContextAdapter> browserContext);
+
bool m_ignoreCertificateErrors;
- QAtomicInt m_updateCookieStore;
- QAtomicInt m_updateHttpCache;
- QAtomicInt m_updateJobFactory;
- QSharedPointer<BrowserContextAdapter> m_browserContext;
+
+ QMutex m_mutex;
+ bool m_contextInitialized;
+ bool m_updateAllStorage;
+ bool m_updateCookieStore;
+ bool m_updateHttpCache;
+ bool m_updateJobFactory;
+ bool m_updateUserAgent;
+
+ QWeakPointer<BrowserContextAdapter> m_browserContext;
content::ProtocolHandlerMap m_protocolHandlers;
QAtomicPointer<net::ProxyConfigService> m_proxyConfigService;
@@ -115,7 +125,20 @@ private:
scoped_refptr<CookieMonsterDelegateQt> m_cookieDelegate;
content::URLRequestInterceptorScopedVector m_requestInterceptors;
scoped_ptr<net::HttpNetworkSession> m_httpNetworkSession;
+
QList<QByteArray> m_installedCustomSchemes;
+ QWebEngineUrlRequestInterceptor* m_requestInterceptor;
+
+ // Configuration values to setup URLRequestContext in IO thread, copied from browserContext
+ // FIXME: Should later be moved to a separate ProfileIOData class.
+ BrowserContextAdapter::PersistentCookiesPolicy m_persistentCookiesPolicy;
+ QString m_cookiesPath;
+ QString m_httpAcceptLanguage;
+ QString m_httpUserAgent;
+ BrowserContextAdapter::HttpCacheType m_httpCacheType;
+ QString m_httpCachePath;
+ int m_httpCacheMaxSize;
+ QList<QByteArray> m_customUrlSchemes;
friend class NetworkDelegateQt;
};
diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp
index 116cd704e..82d21696c 100644
--- a/src/core/web_contents_adapter.cpp
+++ b/src/core/web_contents_adapter.cpp
@@ -520,6 +520,7 @@ void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeT
params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE;
d->webContents->GetController().LoadURLWithParams(params);
d->webContents->Focus();
+ d->webContents->Unselect();
}
void WebContentsAdapter::save()
diff --git a/src/core/web_engine_library_info.cpp b/src/core/web_engine_library_info.cpp
index a67bce94c..2de3d39ff 100644
--- a/src/core/web_engine_library_info.cpp
+++ b/src/core/web_engine_library_info.cpp
@@ -211,20 +211,12 @@ QString dictionariesPath()
#if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD)
return getResourcesPath(frameworkBundle()) % QLatin1String("/qtwebengine_dictionaries");
#else
- static bool initialized = false;
- static QString potentialDictionariesPath = QLibraryInfo::location(QLibraryInfo::DataPath) % QDir::separator() % QLatin1String("qtwebengine_dictionaries");
+ // first local path
+ static QString potentialDictionariesPath = QCoreApplication::applicationDirPath() % QDir::separator() % QLatin1String("qtwebengine_dictionaries");
- if (!initialized) {
- initialized = true;
- if (!QFileInfo::exists(potentialDictionariesPath)) {
- qWarning("Installed Qt WebEngine dictionaries directory not found at location %s. Trying application directory...", qPrintable(potentialDictionariesPath));
- potentialDictionariesPath = QCoreApplication::applicationDirPath() % QDir::separator() % QLatin1String("qtwebengine_dictionaries");
- }
- if (!QFileInfo::exists(potentialDictionariesPath)) {
- qWarning("Qt WebEngine dictionaries directory not found at location %s. Trying fallback directory... Spellcheck MAY NOT work.", qPrintable(potentialDictionariesPath));
- potentialDictionariesPath = fallbackDir();
- }
- }
+ // now global one
+ if (!QFileInfo::exists(potentialDictionariesPath))
+ potentialDictionariesPath = QLibraryInfo::location(QLibraryInfo::DataPath) % QDir::separator() % QLatin1String("qtwebengine_dictionaries");
return potentialDictionariesPath;
#endif
diff --git a/src/process/process.pro b/src/process/process.pro
index cdda429e7..cd60b1f91 100644
--- a/src/process/process.pro
+++ b/src/process/process.pro
@@ -16,6 +16,8 @@ win32 {
load(qt_app)
+contains(QT_CONFIG, build_all): CONFIG += build_all
+
contains(QT_CONFIG, qt_framework) {
# Deploy the QtWebEngineProcess app bundle into the QtWebEngineCore framework.
DESTDIR = $$MODULE_BASE_OUTDIR/lib/QtWebEngineCore.framework/Versions/5/Helpers
diff --git a/src/src.pro b/src/src.pro
index 6a6a6abb8..64c1703fe 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -17,6 +17,13 @@ SUBDIRS += core \
webengine_experimental_plugin \
plugins
+# allow only desktop builds of qwebengine_convert_dict
+# osx does not use hunspell
+!contains(WEBENGINE_CONFIG, no_spellcheck):!osx:!cross_compile {
+ SUBDIRS += qwebengine_convert_dict
+ qwebengine_convert_dict.subdir = tools/qwebengine_convert_dict
+ qwebengine_convert_dict.depends = core
+}
isQMLTestSupportApiEnabled() {
webengine_testsupport_plugin.subdir = webengine/plugin/testsupport
diff --git a/src/tools/qwebengine_convert_dict/main.cpp b/src/tools/qwebengine_convert_dict/main.cpp
new file mode 100644
index 000000000..2142b5f0d
--- /dev/null
+++ b/src/tools/qwebengine_convert_dict/main.cpp
@@ -0,0 +1,183 @@
+/******************************************************************************
+** This is just slightly modified version of convert_dict.cc
+** chromium/chrome/tools/convert_dict/convert_dict.cc
+**
+** Original work:
+** Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+** Modified work:
+** Copyright (C) 2016 The Qt Company Ltd.
+**
+** Use of this source code is governed by a BSD-style license that can be
+** found in the LICENSE file.
+**
+** This tool converts Hunspell .aff/.dic pairs to a combined binary dictionary
+** format (.bdic). This format is more compact, and can be more efficiently
+** read by the client application.
+**
+******************************************************************************/
+
+#include <base/at_exit.h>
+#include <base/files/file_path.h>
+#include <base/files/file_util.h>
+#include <base/i18n/icu_util.h>
+#include <build/build_config.h>
+#include <chrome/tools/convert_dict/aff_reader.h>
+#include <chrome/tools/convert_dict/dic_reader.h>
+#include <third_party/hunspell/google/bdict_reader.h>
+#include <third_party/hunspell/google/bdict_writer.h>
+#include <base/path_service.h>
+
+#include <QTextStream>
+#include <QLibraryInfo>
+#include <QDir>
+
+// see also src/core/type_conversion.h
+inline base::FilePath::StringType toFilePathString(const QString &str)
+{
+#if defined(Q_OS_WIN)
+ return QDir::toNativeSeparators(str).toStdWString();
+#else
+ return str.toStdString();
+#endif
+}
+
+inline base::FilePath toFilePath(const QString &str)
+{
+ return base::FilePath(toFilePathString(str));
+}
+
+inline QString toQt(const base::string16 &string)
+{
+#if defined(OS_WIN)
+ return QString::fromStdWString(string.data());
+#else
+ return QString::fromUtf16(string.data());
+#endif
+}
+
+inline QString toQt(const std::string &string)
+{
+ return QString::fromStdString(string);
+}
+
+// Compares the given word list with the serialized trie to make sure they
+// are the same.
+inline bool VerifyWords(const convert_dict::DicReader::WordList& org_words,
+ const std::string& serialized, QTextStream& out)
+{
+ hunspell::BDictReader reader;
+ if (!reader.Init(reinterpret_cast<const unsigned char*>(serialized.data()),
+ serialized.size())) {
+ out << "BDict is invalid" << endl;
+ return false;
+ }
+ hunspell::WordIterator iter = reader.GetAllWordIterator();
+
+ int affix_ids[hunspell::BDict::MAX_AFFIXES_PER_WORD];
+
+ static const int buf_size = 128;
+ char buf[buf_size];
+ for (size_t i = 0; i < org_words.size(); i++) {
+ int affix_matches = iter.Advance(buf, buf_size, affix_ids);
+ if (affix_matches == 0) {
+ out << "Found the end before we expected" << endl;
+ return false;
+ }
+
+ if (org_words[i].first != buf) {
+ out << "Word doesn't match, word #" << buf << endl;
+ return false;
+ }
+
+ if (affix_matches != static_cast<int>(org_words[i].second.size())) {
+ out << "Different number of affix indices, word #" << buf << endl;
+ return false;
+ }
+
+ // Check the individual affix indices.
+ for (size_t affix_index = 0; affix_index < org_words[i].second.size();
+ affix_index++) {
+ if (affix_ids[affix_index] != org_words[i].second[affix_index]) {
+ out << "Index doesn't match, word #" << buf << endl;
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+int main(int argc, char *argv[])
+{
+ QTextStream out(stdout);
+
+ if (argc != 3) {
+ QTextStream out(stdout);
+ out << "Usage: qwebengine_convert_dict <dic file> <bdic file>\n\nExample:\n"
+ "qwebengine_convert_dict ./en-US.dic ./en-US.bdic\nwill read en-US.dic, "
+ "en-US.dic_delta, and en-US.aff from the current directory and generate "
+ "en-US.bdic\n" << endl;
+ return 1;
+ }
+
+ PathService::Override(base::DIR_QT_LIBRARY_DATA,
+ toFilePath(QLibraryInfo::location(QLibraryInfo::DataPath) %
+ QLatin1String("/resources")));
+
+ base::AtExitManager exit_manager;
+ base::i18n::InitializeICU();
+
+ base::FilePath file_in_path = toFilePath(argv[1]);
+ base::FilePath file_out_path = toFilePath(argv[2]);
+ base::FilePath aff_path = file_in_path.ReplaceExtension(FILE_PATH_LITERAL(".aff"));
+
+ out << "Reading " << toQt(aff_path.value()) << endl;
+ convert_dict::AffReader aff_reader(aff_path);
+
+ if (!aff_reader.Read()) {
+ out << "Unable to read the aff file." << endl;
+ return 1;
+ }
+
+ base::FilePath dic_path = file_in_path.ReplaceExtension(FILE_PATH_LITERAL(".dic"));
+ out << "Reading " << toQt(dic_path.value()) << endl;
+
+ // DicReader will also read the .dic_delta file.
+ convert_dict::DicReader dic_reader(dic_path);
+ if (!dic_reader.Read(&aff_reader)) {
+ out << "Unable to read the dic file." << endl;
+ return 1;
+ }
+
+ hunspell::BDictWriter writer;
+ writer.SetComment(aff_reader.comments());
+ writer.SetAffixRules(aff_reader.affix_rules());
+ writer.SetAffixGroups(aff_reader.GetAffixGroups());
+ writer.SetReplacements(aff_reader.replacements());
+ writer.SetOtherCommands(aff_reader.other_commands());
+ writer.SetWords(dic_reader.words());
+
+ out << "Serializing..." << endl;
+
+ std::string serialized = writer.GetBDict();
+
+ out << "Verifying..." << endl;
+
+ if (!VerifyWords(dic_reader.words(), serialized, out)) {
+ out << "ERROR converting, the dictionary does not check out OK." << endl;
+ return 1;
+ }
+
+ out << "Writing " << toQt(file_out_path.value()) << endl;
+ FILE *out_file = base::OpenFile(file_out_path, "wb");
+ if (!out_file) {
+ out << "ERROR writing file" << endl;
+ return 1;
+ }
+ size_t written = fwrite(&serialized[0], 1, serialized.size(), out_file);
+ Q_ASSERT(written == serialized.size());
+ base::CloseFile(out_file);
+ out << "Success. Dictionary converted." << endl;
+ return 0;
+}
+
diff --git a/src/tools/qwebengine_convert_dict/qwebengine_convert_dict.pro b/src/tools/qwebengine_convert_dict/qwebengine_convert_dict.pro
new file mode 100644
index 000000000..de125cc76
--- /dev/null
+++ b/src/tools/qwebengine_convert_dict/qwebengine_convert_dict.pro
@@ -0,0 +1,22 @@
+option(host_build)
+
+# Look for linking information produced by gyp for our target according to core_generated.gyp
+!include($$OUT_PWD/../../core/$$getConfigDir()/QtWebEngineCore_linking.pri) {
+ error("Could not find the linking information that gyp should have generated.")
+}
+# remove object files from linking information
+OBJECTS =
+
+# Fixme: -Werror=unused-parameter in core
+QMAKE_CXXFLAGS_WARN_ON =
+
+# Issue with some template compliation, smb smart should look at it
+win32: DEFINES += NOMINMAX
+
+CHROMIUM_SRC_DIR = $$QTWEBENGINE_ROOT/$$getChromiumSrcDir()
+INCLUDEPATH += $$CHROMIUM_SRC_DIR
+
+SOURCES += \
+ main.cpp
+
+load(qt_tool)
diff --git a/src/webengine/api/qquickwebenginecontextmenudata.cpp b/src/webengine/api/qquickwebenginecontextmenudata.cpp
index 221b42245..684903ec0 100644
--- a/src/webengine/api/qquickwebenginecontextmenudata.cpp
+++ b/src/webengine/api/qquickwebenginecontextmenudata.cpp
@@ -170,30 +170,6 @@ bool QQuickWebEngineContextMenuData::isContentEditable() const
return d ? d->isEditable : false;
}
-/*!
- \qmlproperty QString WebEngineDownloadItem::misspelledWord
-
- If the context is a word considered misspelled by the spell-checker, returns the misspelled word.
-*/
-QString QQuickWebEngineContextMenuData::misspelledWord() const
-{
- if (d)
- return d->misspelledWord;
- return QString();
-}
-
-/*!
- \qmlproperty QStringList WebEngineDownloadItem::spellCheckerSuggestions
-
- If the context is a word considered misspelled by the spell-checker, returns a list of suggested replacements.
-*/
-QStringList QQuickWebEngineContextMenuData::spellCheckerSuggestions() const
-{
- if (d)
- return d->spellCheckerSuggestions;
- return QStringList();
-}
-
void QQuickWebEngineContextMenuData::update(const QtWebEngineCore::WebEngineContextMenuData &update)
{
const QQuickWebEngineContextMenuData old(d);
@@ -222,12 +198,6 @@ void QQuickWebEngineContextMenuData::update(const QtWebEngineCore::WebEngineCont
if (isContentEditable() != old.isContentEditable())
Q_EMIT isContentEditableChanged();
-
- if (misspelledWord() != old.misspelledWord())
- Q_EMIT misspelledWordChanged();
-
- if (spellCheckerSuggestions() != old.spellCheckerSuggestions())
- Q_EMIT spellCheckerSuggestionsChanged();
}
QQuickWebEngineContextMenuData::QQuickWebEngineContextMenuData(const QQuickWebEngineContextMenuDataPrivate *p, QObject *parent)
diff --git a/src/webengine/api/qquickwebenginecontextmenudata_p.h b/src/webengine/api/qquickwebenginecontextmenudata_p.h
index 0989eaa5a..aa081cbe6 100644
--- a/src/webengine/api/qquickwebenginecontextmenudata_p.h
+++ b/src/webengine/api/qquickwebenginecontextmenudata_p.h
@@ -92,8 +92,6 @@ public:
Q_PROPERTY(QUrl mediaUrl READ mediaUrl NOTIFY mediaUrlChanged)
Q_PROPERTY(MediaType mediaType READ mediaType NOTIFY mediaTypeChanged)
Q_PROPERTY(bool isContentEditable READ isContentEditable NOTIFY isContentEditableChanged)
- Q_PROPERTY(QString misspelledWord READ misspelledWord NOTIFY misspelledWordChanged)
- Q_PROPERTY(QStringList spellCheckerSuggestions READ spellCheckerSuggestions NOTIFY spellCheckerSuggestionsChanged)
bool isValid() const;
@@ -105,9 +103,6 @@ public:
MediaType mediaType() const;
bool isContentEditable() const;
- QString misspelledWord() const;
- QStringList spellCheckerSuggestions() const;
-
Q_SIGNALS:
void isValidChanged();
void positionChanged();
@@ -117,8 +112,6 @@ Q_SIGNALS:
void mediaUrlChanged();
void mediaTypeChanged();
void isContentEditableChanged();
- void misspelledWordChanged();
- void spellCheckerSuggestionsChanged();
private:
void update(const QtWebEngineCore::WebEngineContextMenuData &update);
diff --git a/src/webengine/api/qquickwebenginefaviconprovider.cpp b/src/webengine/api/qquickwebenginefaviconprovider.cpp
index c41ec5a07..fe8436d6c 100644
--- a/src/webengine/api/qquickwebenginefaviconprovider.cpp
+++ b/src/webengine/api/qquickwebenginefaviconprovider.cpp
@@ -121,12 +121,13 @@ QPixmap QQuickWebEngineFaviconProvider::requestPixmap(const QString &id, QSize *
return QPixmap();
FaviconManager *faviconManager = view->d_ptr->adapter->faviconManager();
- Q_ASSERT(faviconManager);
- const QIcon &icon = faviconManager->getIcon(iconUrl);
+ Q_ASSERT(faviconManager);
+ const FaviconInfo &faviconInfo = faviconManager->getFaviconInfo(iconUrl);
+ const QIcon &icon = faviconManager->getIcon(faviconInfo.candidate ? QUrl() : iconUrl);
Q_ASSERT(!icon.isNull());
- const QSize &bestSize = faviconManager->getFaviconInfo(iconUrl).size;
+ const QSize &bestSize = faviconInfo.size;
// If source size is not specified, use the best quality
if (!requestedSize.isValid()) {
diff --git a/src/webengine/api/qquickwebengineprofile.cpp b/src/webengine/api/qquickwebengineprofile.cpp
index d7a84c106..c1f8f3179 100644
--- a/src/webengine/api/qquickwebengineprofile.cpp
+++ b/src/webengine/api/qquickwebengineprofile.cpp
@@ -613,95 +613,6 @@ QQuickWebEngineProfile *QQuickWebEngineProfile::defaultProfile()
}
/*!
- \qmlmethod void QQuickWebEngineProfile::availableDictionaries()
-
- Returns the subset of \a languages supported by the spell checker.
- Checks whether the spell checker dictionary is installed for the specified
- language from the \a languages list. If the dictionary file is missing
- or corrupted, the language is removed from the returned list.
-
- \since QtWebEngine 1.3
-*/
-
-/*!
- Returns the subset of \a languages supported by the spell checker.
- Checks whether the spell checker dictionary is installed for the specified
- language from the \a languages list. If the dictionary file is missing
- or corrupted, the language is removed from the returned list.
-
- \since QtWebEngine 1.3
-*/
-QStringList QQuickWebEngineProfile::availableDictionaries(const QStringList &languages)
-{
- const Q_D(QQuickWebEngineProfile);
- return d->browserContext()->spellCheckLanguages(languages);
-}
-
-/*!
- \property QQuickWebEngineProfile::spellCheckLanguage
- \brief the language used by the spell checker.
-
- \since QtWebEngine 1.3
-*/
-
-/*!
- \qmlproperty QString WebEngineProfile::spellCheckLanguage
-
- This property holds the language used by the spell checker.
-
- \since QtWebEngine 1.3
-*/
-void QQuickWebEngineProfile::setSpellCheckLanguage(const QString &language)
-{
- Q_D(QQuickWebEngineProfile);
- if (language != d->browserContext()->spellCheckLanguage()) {
- d->browserContext()->setSpellCheckLanguage(language);
- emit spellCheckLanguageChanged();
- }
-}
-
-/*!
- \since 5.7
-
- Returns the language used by the spell checker.
-*/
-QString QQuickWebEngineProfile::spellCheckLanguage() const
-{
- const Q_D(QQuickWebEngineProfile);
- return d->browserContext()->spellCheckLanguage();
-}
-
-/*!
- \property QQuickWebEngineProfile::spellCheckEnabled
- \brief whether the web engine spell checker is enabled.
-
- \since QtWebEngine 1.3
-*/
-
-/*!
- \qmlproperty QString WebEngineProfile::spellCheckEnabled
-
- This property holds whether the web engine spell checker is enabled.
-
- \since QtWebEngine 1.3
-*/
-void QQuickWebEngineProfile::setSpellCheckEnabled(bool enable)
-{
- Q_D(QQuickWebEngineProfile);
- if (enable != isSpellCheckEnabled()) {
- d->browserContext()->setSpellCheckEnabled(enable);
- emit spellCheckEnabledChanged();
- }
-}
-
-bool QQuickWebEngineProfile::isSpellCheckEnabled() const
-{
- const Q_D(QQuickWebEngineProfile);
- return d->browserContext()->isSpellCheckEnabled();
-}
-
-/*!
-
Returns the cookie store for this profile.
*/
QWebEngineCookieStore *QQuickWebEngineProfile::cookieStore() const
diff --git a/src/webengine/api/qquickwebengineprofile.h b/src/webengine/api/qquickwebengineprofile.h
index 8d120d10e..4f9684a86 100644
--- a/src/webengine/api/qquickwebengineprofile.h
+++ b/src/webengine/api/qquickwebengineprofile.h
@@ -71,8 +71,6 @@ class Q_WEBENGINE_EXPORT QQuickWebEngineProfile : public QObject {
Q_PROPERTY(QString httpAcceptLanguage READ httpAcceptLanguage WRITE setHttpAcceptLanguage NOTIFY httpAcceptLanguageChanged FINAL REVISION 1)
Q_PROPERTY(PersistentCookiesPolicy persistentCookiesPolicy READ persistentCookiesPolicy WRITE setPersistentCookiesPolicy NOTIFY persistentCookiesPolicyChanged FINAL)
Q_PROPERTY(int httpCacheMaximumSize READ httpCacheMaximumSize WRITE setHttpCacheMaximumSize NOTIFY httpCacheMaximumSizeChanged FINAL)
- Q_PROPERTY(QString spellCheckLanguage READ spellCheckLanguage WRITE setSpellCheckLanguage NOTIFY spellCheckLanguageChanged FINAL REVISION 2)
- Q_PROPERTY(bool spellCheckEnabled READ isSpellCheckEnabled WRITE setSpellCheckEnabled NOTIFY spellCheckEnabledChanged FINAL REVISION 2)
public:
QQuickWebEngineProfile(QObject *parent = Q_NULLPTR);
@@ -131,12 +129,6 @@ public:
void clearHttpCache();
- Q_REVISION(2) Q_INVOKABLE QStringList availableDictionaries(const QStringList &languages);
- Q_REVISION(2) void setSpellCheckLanguage(const QString &language);
- Q_REVISION(2) QString spellCheckLanguage() const;
- Q_REVISION(2) void setSpellCheckEnabled(bool enabled);
- Q_REVISION(2) bool isSpellCheckEnabled() const;
-
static QQuickWebEngineProfile *defaultProfile();
Q_SIGNALS:
@@ -149,8 +141,6 @@ Q_SIGNALS:
void persistentCookiesPolicyChanged();
void httpCacheMaximumSizeChanged();
Q_REVISION(1) void httpAcceptLanguageChanged();
- Q_REVISION(2) void spellCheckLanguageChanged();
- Q_REVISION(2) void spellCheckEnabledChanged();
void downloadRequested(QQuickWebEngineDownloadItem *download);
void downloadFinished(QQuickWebEngineDownloadItem *download);
diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp
index f265ccfb6..1b1dcec25 100644
--- a/src/webengine/api/qquickwebengineview.cpp
+++ b/src/webengine/api/qquickwebengineview.cpp
@@ -202,16 +202,7 @@ bool QQuickWebEngineViewPrivate::contextMenuRequested(const WebEngineContextMenu
// Populate our menu
MenuItemHandler *item = 0;
- if (contextMenuData.isContentEditable() && !contextMenuData.spellCheckerSuggestions().isEmpty()) {
- const QPointer<QQuickWebEngineView> qRef(q);
- for (int i=0; i < contextMenuData.spellCheckerSuggestions().count() && i < 4; i++) {
- item = new MenuItemHandler(menu);
- QString replacement = contextMenuData.spellCheckerSuggestions().at(i);
- QObject::connect(item, &MenuItemHandler::triggered, [qRef, replacement] { qRef->replaceMisspelledWord(replacement); });
- ui()->addMenuItem(item, replacement);
- }
- ui()->addMenuSeparator(menu);
- }
+
if (!data.linkText.isEmpty() && data.linkUrl.isValid()) {
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::OpenLinkInThisWindow); });
@@ -1237,12 +1228,6 @@ void QQuickWebEngineView::printToPdf(const QJSValue &callback, PrintedPageSizeId
d->m_callbacks.insert(requestId, callback);
}
-void QQuickWebEngineView::replaceMisspelledWord(const QString &replacement)
-{
- Q_D(QQuickWebEngineView);
- d->adapter->replaceMisspelling(replacement);
-}
-
bool QQuickWebEngineView::isFullScreen() const
{
Q_D(const QQuickWebEngineView);
diff --git a/src/webengine/api/qquickwebengineview_p.h b/src/webengine/api/qquickwebengineview_p.h
index 843e34f42..d287b46ca 100644
--- a/src/webengine/api/qquickwebengineview_p.h
+++ b/src/webengine/api/qquickwebengineview_p.h
@@ -471,8 +471,6 @@ public Q_SLOTS:
Q_REVISION(2) void triggerWebAction(WebAction action);
Q_REVISION(3) void printToPdf(const QString &filePath, PrintedPageSizeId pageSizeId = PrintedPageSizeId::A4, PrintedPageOrientation orientation = PrintedPageOrientation::Portrait);
Q_REVISION(3) void printToPdf(const QJSValue &callback, PrintedPageSizeId pageSizeId = PrintedPageSizeId::A4, PrintedPageOrientation orientation = PrintedPageOrientation::Portrait);
- Q_REVISION(3) void replaceMisspelledWord(const QString &replacement);
-
private Q_SLOTS:
void lazyInitialize();
diff --git a/src/webengine/doc/src/qtwebengine-platform-notes.qdoc b/src/webengine/doc/src/qtwebengine-platform-notes.qdoc
index dec9d0407..4bb449016 100644
--- a/src/webengine/doc/src/qtwebengine-platform-notes.qdoc
+++ b/src/webengine/doc/src/qtwebengine-platform-notes.qdoc
@@ -46,6 +46,8 @@
\section1 Building Qt WebEngine from Source
+ Static builds are not supported.
+
The requirements for building Qt 5 modules from source are listed separately for each supported
platform:
@@ -58,13 +60,63 @@
In addition, the following tools are required for building the \l {Qt WebEngine} module:
\list
- \li Windows: Visual Studio 2013 or Visual Studio 2015
- \li Linux: Clang or GCC version 4.7 or later
- \li OS X: Xcode version 5.1 or later on OS X 10.9 or later
+ \li \l {All Platforms}
+ \li \l {Windows}
+ \li \l {Linux}
+ \li \l {OS X}
+ \endlist
+
+ The tests for skipping the Qt WebEngine build are located in the
+ \c qtwebengine repository, in the \c tools\qmake\mkspecs subdirectory.
+ They can be found by searching for \c skipBuild.
+
+ \section2 All Platforms
+
+ On all platforms, the following tools are required:
+
+ \list
+ \li \l Python 2.7 or later
+ \li Bison, Flex
+ \li GPerf
+ \endlist
+
+ \section2 Windows
+
+ On Windows, Visual Studio 2013 or Visual Studio 2015 is required.
+
+ \section2 Linux
+
+ On Linux, Clang or GCC version 4.7 or later is required.
+
+ Qt WebEngine requires \c pkg-config to detect most of its dependencies. The
+ following \c pkg-config files are required:
+
+ \list
+ \li \c dbus-1
+ \li \c fontconfig
\endlist
+ If Qt was configured for \c xcb, the following \c pkg-config files are also
+ required:
+
+ \list
+ \li \c libdrm
+ \li \c xcomposite
+ \li \c xcursor
+ \li \c xi
+ \li \c xrandr
+ \li \c xscrnsaver
+ \li \c xtst
+ \endlist
+
+ Further, development packages for \c khr and \c libcap need to be installed.
+
+ \section2 OS X
+
+ On OS X, Xcode version 5.1 or later on OS X 10.9 or later is required.
+
\note Qt WebEngine cannot be built for the 32-bit mode of OS X (using the
- macx-clang-32 mkspec).
+ \c macx-clang-32 \c mkspec).
\section1 Pepper Plugin API Support
diff --git a/src/webengine/doc/src/webengineview.qdoc b/src/webengine/doc/src/webengineview.qdoc
index a070140c7..444f0f398 100644
--- a/src/webengine/doc/src/webengineview.qdoc
+++ b/src/webengine/doc/src/webengineview.qdoc
@@ -215,10 +215,17 @@
\qml
Image {
id: appIcon
+ sourceSize: Qt.size(32, 32)
source: webView.icon != "" ? webView.icon : "fallbackFavicon.png";
// ...
}
\endqml
+
+ Specifying the \c{sourceSize} property of the \c{Image} element informs
+ the Qt WebEngine's favicon provider about the requested size. The
+ favicon provider tries to find the best fit among the web page candidate
+ icons. If \c{sourceSize} property is not specified, the provider provides
+ the icon with the largest resolution.
*/
/*!
@@ -1042,7 +1049,7 @@
This signal is emitted when the page's audio is (un)muted using audioMuted property.
\note Not to be confused with a specific HTML5 audio / video element being muted.
- \sa audioMuted
+ \sa audioMuted, recentlyAudibleChanged
*/
/*!
@@ -1050,7 +1057,7 @@
\brief Returns the current page's audible state (audio was recently played, or not).
\since QtWebEngine 1.3
\readonly
- \sa audioMuted
+ \sa audioMuted, recentlyAudibleChanged
*/
/*!
@@ -1064,6 +1071,20 @@
Also if the audio is paused, this signal is emitted with an approximate \b{two-second
delay}, from the moment the audio is paused.
+ This signal is also emitted for Flash plugin audio.
+
+ If a web page contains two videos that are started in sequence, this signal
+ gets emitted only once, for the first video to generate sound. After both
+ videos are stopped, the signal is emitted upon the last sound generated.
+ This means that the signal is emitted both when any kind of sound is
+ generated and when everything is completely silent within a web page,
+ regardless of the number of audio streams.
+
+ Spurious signal emissions might also happen. For example, when sound is
+ stopped, this signal gets emitted first with a value of \c true, and then
+ with a value of \c false. Further, when audio starts playing, the signal is
+ emitted twice with a value of \c true.
+
\sa recentlyAudible
*/
diff --git a/src/webenginewidgets/api/qwebenginecontextmenudata.cpp b/src/webenginewidgets/api/qwebenginecontextmenudata.cpp
index 17a562ea1..c7019977b 100644
--- a/src/webenginewidgets/api/qwebenginecontextmenudata.cpp
+++ b/src/webenginewidgets/api/qwebenginecontextmenudata.cpp
@@ -187,26 +187,6 @@ bool QWebEngineContextMenuData::isContentEditable() const
}
/*!
- If the context is a word considered misspelled by the spell-checker, returns the misspelled word.
-*/
-QString QWebEngineContextMenuData::misspelledWord() const
-{
- if (d)
- return d->misspelledWord;
- return QString();
-}
-
-/*!
- If the context is a word considered misspelled by the spell-checker, returns a list of suggested replacements.
-*/
-QStringList QWebEngineContextMenuData::spellCheckerSuggestions() const
-{
- if (d)
- return d->spellCheckerSuggestions;
- return QStringList();
-}
-
-/*!
\internal
*/
QWebEngineContextMenuData &QWebEngineContextMenuData::operator=(const QWebEngineContextDataPrivate &priv)
diff --git a/src/webenginewidgets/api/qwebenginecontextmenudata.h b/src/webenginewidgets/api/qwebenginecontextmenudata.h
index fd1080eec..4bea34ee0 100644
--- a/src/webenginewidgets/api/qwebenginecontextmenudata.h
+++ b/src/webenginewidgets/api/qwebenginecontextmenudata.h
@@ -76,8 +76,6 @@ public:
QUrl mediaUrl() const;
MediaType mediaType() const;
bool isContentEditable() const;
- QString misspelledWord() const;
- QStringList spellCheckerSuggestions() const;
private:
void reset();
diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp
index 447c53ba9..0e7f02f16 100644
--- a/src/webenginewidgets/api/qwebenginepage.cpp
+++ b/src/webenginewidgets/api/qwebenginepage.cpp
@@ -151,7 +151,7 @@ void QWebEnginePagePrivate::iconChanged(const QUrl &url)
return;
iconUrl = url;
Q_EMIT q->iconUrlChanged(iconUrl);
- Q_EMIT q->iconChanged(adapter->faviconManager()->getIcon(iconUrl));
+ Q_EMIT q->iconChanged(adapter->faviconManager()->getIcon());
}
void QWebEnginePagePrivate::loadProgressChanged(int progress)
@@ -1098,22 +1098,6 @@ void QWebEnginePage::triggerAction(WebAction action, bool)
}
}
-/*!
- * \since 5.7
- * Replace the current misspelled word with \a replacement.
- *
- * The current misspelled word can be found in QWebEngineContextMenuData::misspelledWord(),
- * and suggested replacements in QWebEngineContextMenuData::spellCheckerSuggestions().
- *
- * \sa contextMenuData(),
- */
-
-void QWebEnginePage::replaceMisspelledWord(const QString &replacement)
-{
- Q_D(QWebEnginePage);
- d->adapter->replaceMisspelling(replacement);
-}
-
void QWebEnginePage::findText(const QString &subString, FindFlags options, const QWebEngineCallback<bool> &resultCallback)
{
Q_D(QWebEnginePage);
@@ -1292,18 +1276,6 @@ QMenu *QWebEnginePage::createStandardContextMenu()
QAction *action = 0;
const WebEngineContextMenuData &contextMenuData = *d->contextData.d;
- if (contextMenuData.isEditable && !contextMenuData.spellCheckerSuggestions.isEmpty()) {
- QPointer<QWebEnginePage> thisRef(this);
- for (int i=0; i < contextMenuData.spellCheckerSuggestions.count() && i < 4; i++) {
- QAction *action = new QAction(menu);
- QString replacement = contextMenuData.spellCheckerSuggestions.at(i);
- QObject::connect(action, &QAction::triggered, [thisRef, replacement] { if (thisRef) thisRef->replaceMisspelledWord(replacement); });
- action->setText(replacement);
- menu->addAction(action);
- }
- menu->addSeparator();
- }
-
if (!contextMenuData.linkText.isEmpty() && contextMenuData.linkUrl.isValid()) {
action = QWebEnginePage::action(OpenLinkInThisWindow);
action->setText(tr("Follow Link"));
@@ -1506,7 +1478,9 @@ QUrl QWebEnginePage::iconUrl() const
\brief the icon associated with the page currently viewed
\since 5.7
- By default, this property contains a null icon.
+ By default, this property contains a null icon. If the web page specifies more than one icon,
+ the \c{icon} property encapsulates the available candidate icons in a single,
+ scalable \c{QIcon}.
\sa iconChanged(), iconUrl(), iconUrlChanged()
*/
@@ -1517,7 +1491,7 @@ QIcon QWebEnginePage::icon() const
if (d->iconUrl.isEmpty())
return QIcon();
- return d->adapter->faviconManager()->getIcon(d->iconUrl);
+ return d->adapter->faviconManager()->getIcon();
}
qreal QWebEnginePage::zoomFactor() const
diff --git a/src/webenginewidgets/api/qwebenginepage.h b/src/webenginewidgets/api/qwebenginepage.h
index 7b99270c0..0c6450d20 100644
--- a/src/webenginewidgets/api/qwebenginepage.h
+++ b/src/webenginewidgets/api/qwebenginepage.h
@@ -206,8 +206,6 @@ public:
#endif
virtual void triggerAction(WebAction action, bool checked = false);
- void replaceMisspelledWord(const QString &replacement);
-
virtual bool event(QEvent*);
#ifdef Q_QDOC
void findText(const QString &subString, FindFlags options = 0);
diff --git a/src/webenginewidgets/api/qwebengineprofile.cpp b/src/webenginewidgets/api/qwebengineprofile.cpp
index 2dab0aa08..664323034 100644
--- a/src/webenginewidgets/api/qwebengineprofile.cpp
+++ b/src/webenginewidgets/api/qwebengineprofile.cpp
@@ -556,68 +556,6 @@ QWebEngineProfile *QWebEngineProfile::defaultProfile()
}
/*!
- \since 5.7
-
- Returns the subset of \a languages supported by the spell checker.
-
- Checks whether the spell checker dictionary is installed for the specified
- language from the \a languages list. If the dictionary file is missing
- or corrupted, the language is removed from the returned list.
-
- \sa setSpellCheckLanguage()
-*/
-QStringList QWebEngineProfile::availableDictionaries(const QStringList &languages)
-{
- const Q_D(QWebEngineProfile);
- return d->browserContext()->spellCheckLanguages(languages);
-}
-
-/*!
- \since 5.7
-
- Sets the current \a language for the spell checker.
-*/
-void QWebEngineProfile::setSpellCheckLanguage(const QString &language)
-{
- Q_D(QWebEngineProfile);
- d->browserContext()->setSpellCheckLanguage(language);
-}
-
-/*!
- \since 5.7
-
- Returns the language used by the spell checker.
-*/
-QString QWebEngineProfile::spellCheckLanguage() const
-{
- const Q_D(QWebEngineProfile);
- return d->browserContext()->spellCheckLanguage();
-}
-
-/*!
- \since 5.7
-
- Enables spell checker if \a enable is \c true, otherwise disables it.
- \sa isSpellCheckEnabled()
- */
-void QWebEngineProfile::setSpellCheckEnabled(bool enable)
-{
- Q_D(QWebEngineProfile);
- d->browserContext()->setSpellCheckEnabled(enable);
-}
-/*!
- \since 5.7
-
- Returns \c true if the spell checker is enabled; otherwise returns \c false.
- \sa setSpellCheckEnabled()
- */
-bool QWebEngineProfile::isSpellCheckEnabled() const
-{
- const Q_D(QWebEngineProfile);
- return d->browserContext()->isSpellCheckEnabled();
-}
-
-/*!
Returns the default settings for all pages in this profile.
*/
QWebEngineSettings *QWebEngineProfile::settings() const
diff --git a/src/webenginewidgets/api/qwebengineprofile.h b/src/webenginewidgets/api/qwebengineprofile.h
index 9c473eee9..22a913fb2 100644
--- a/src/webenginewidgets/api/qwebengineprofile.h
+++ b/src/webenginewidgets/api/qwebengineprofile.h
@@ -121,12 +121,6 @@ public:
void clearHttpCache();
- QStringList availableDictionaries(const QStringList &languages);
- void setSpellCheckLanguage(const QString &language);
- QString spellCheckLanguage() const;
- void setSpellCheckEnabled(bool enabled);
- bool isSpellCheckEnabled() const;
-
static QWebEngineProfile *defaultProfile();
Q_SIGNALS:
diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp
index 396e6950d..6171391e3 100644
--- a/src/webenginewidgets/api/qwebengineview.cpp
+++ b/src/webenginewidgets/api/qwebengineview.cpp
@@ -321,6 +321,7 @@ bool QWebEngineView::event(QEvent *ev)
void QWebEngineView::contextMenuEvent(QContextMenuEvent *event)
{
QMenu *menu = page()->createStandardContextMenu();
+ connect(menu, &QMenu::aboutToHide, menu, &QObject::deleteLater);
menu->popup(event->globalPos());
}
diff --git a/tests/auto/quick/qmltests/data/favicon-candidates-gray.html b/tests/auto/quick/qmltests/data/favicon-candidates-gray.html
new file mode 100644
index 000000000..3cbc4a4c3
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/favicon-candidates-gray.html
@@ -0,0 +1,29 @@
+<html>
+ <head>
+ <title>Gray Candidate Favicons Test</title>
+ <link rel="shortcut icon" href="icons/gray16.png" />
+ <link rel="shortcut icon" href="icons/gray32.png" />
+ <link rel="shortcut icon" href="icons/gray64.png" />
+ <link rel="shortcut icon" href="icons/gray128.png" />
+ <link rel="shortcut icon" href="icons/gray255.png" />
+ </head>
+ <body>
+ <h1>Gray Candidate Favicons Test</h1>
+ <table style="width:100%">
+ <tr>
+ <td align="center"><img src="icons/gray16.png" height="16" width="16" /></td>
+ <td align="center"><img src="icons/gray32.png" height="32" width="32" /></td>
+ <td align="center"><img src="icons/gray64.png" height="64" width="64" /></td>
+ <td align="center"><img src="icons/gray128.png" height="128" width="128" /></td>
+ <td align="center"><img src="icons/gray255.png" height="255" width="255" /></td>
+ </tr>
+ <tr>
+ <td align="center">16x16</td>
+ <td align="center">32x32</td>
+ <td align="center">64x64</td>
+ <td align="center">128x128</td>
+ <td align="center">255x255</td>
+ </tr>
+ </table>
+ </body>
+</html>
diff --git a/tests/auto/quick/qmltests/data/favicon-multi-gray.html b/tests/auto/quick/qmltests/data/favicon-multi-gray.html
index d6ac0909f..9b9b7432d 100644
--- a/tests/auto/quick/qmltests/data/favicon-multi-gray.html
+++ b/tests/auto/quick/qmltests/data/favicon-multi-gray.html
@@ -5,5 +5,21 @@
</head>
<body>
<h1>Gray Multi-sized Favicon Test</h1>
+ <table style="width:100%">
+ <tr>
+ <td align="center"><img src="icons/gray16.png" height="16" width="16" /></td>
+ <td align="center"><img src="icons/gray32.png" height="32" width="32" /></td>
+ <td align="center"><img src="icons/gray64.png" height="64" width="64" /></td>
+ <td align="center"><img src="icons/gray128.png" height="128" width="128" /></td>
+ <td align="center"><img src="icons/gray255.png" height="255" width="255" /></td>
+ </tr>
+ <tr>
+ <td align="center">16x16</td>
+ <td align="center">32x32</td>
+ <td align="center">64x64</td>
+ <td align="center">128x128</td>
+ <td align="center">255x255</td>
+ </tr>
+ </table>
</body>
</html>
diff --git a/tests/auto/quick/qmltests/data/icons/gray128.png b/tests/auto/quick/qmltests/data/icons/gray128.png
new file mode 100644
index 000000000..bf1cfaba0
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/icons/gray128.png
Binary files differ
diff --git a/tests/auto/quick/qmltests/data/icons/gray16.png b/tests/auto/quick/qmltests/data/icons/gray16.png
new file mode 100644
index 000000000..2a1a91a76
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/icons/gray16.png
Binary files differ
diff --git a/tests/auto/quick/qmltests/data/icons/gray255.png b/tests/auto/quick/qmltests/data/icons/gray255.png
new file mode 100644
index 000000000..549169551
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/icons/gray255.png
Binary files differ
diff --git a/tests/auto/quick/qmltests/data/icons/gray32.png b/tests/auto/quick/qmltests/data/icons/gray32.png
new file mode 100644
index 000000000..b269a528f
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/icons/gray32.png
Binary files differ
diff --git a/tests/auto/quick/qmltests/data/icons/gray64.png b/tests/auto/quick/qmltests/data/icons/gray64.png
new file mode 100644
index 000000000..e02559e5b
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/icons/gray64.png
Binary files differ
diff --git a/tests/auto/quick/qmltests/data/tst_favicon.qml b/tests/auto/quick/qmltests/data/tst_favicon.qml
index e959f19be..633859add 100644
--- a/tests/auto/quick/qmltests/data/tst_favicon.qml
+++ b/tests/auto/quick/qmltests/data/tst_favicon.qml
@@ -261,16 +261,26 @@ TestWebEngineView {
function test_faviconProvider_data() {
return [
- { tag: "8x8", size: 8, value: 16 },
- { tag: "16x16", size: 16, value: 16 },
- { tag: "17x17", size: 17, value: 32 },
- { tag: "31x31", size: 31, value: 32 },
- { tag: "32x32", size: 32, value: 32 },
- { tag: "33x33", size: 33, value: 64 },
- { tag: "64x64", size: 64, value: 64 },
- { tag: "128x128", size: 128, value: 128 },
- { tag: "255x255", size: 255, value: 255 },
- { tag: "256x256", size: 256, value: 255 },
+ { tag: "multi 8x8", url: Qt.resolvedUrl("favicon-multi-gray.html"), size: 8, value: 16 },
+ { tag: "multi 16x16", url: Qt.resolvedUrl("favicon-multi-gray.html"), size: 16, value: 16 },
+ { tag: "multi 17x17", url: Qt.resolvedUrl("favicon-multi-gray.html"), size: 17, value: 32 },
+ { tag: "multi 31x31", url: Qt.resolvedUrl("favicon-multi-gray.html"), size: 31, value: 32 },
+ { tag: "multi 32x32", url: Qt.resolvedUrl("favicon-multi-gray.html"), size: 32, value: 32 },
+ { tag: "multi 33x33", url: Qt.resolvedUrl("favicon-multi-gray.html"), size: 33, value: 64 },
+ { tag: "multi 64x64", url: Qt.resolvedUrl("favicon-multi-gray.html"), size: 64, value: 64 },
+ { tag: "multi 128x128", url: Qt.resolvedUrl("favicon-multi-gray.html"), size: 128, value: 128 },
+ { tag: "multi 255x255", url: Qt.resolvedUrl("favicon-multi-gray.html"), size: 255, value: 255 },
+ { tag: "multi 256x256", url: Qt.resolvedUrl("favicon-multi-gray.html"), size: 256, value: 255 },
+ { tag: "candidate 8x8", url: Qt.resolvedUrl("favicon-candidates-gray.html"), size: 8, value: 16 },
+ { tag: "candidate 16x16", url: Qt.resolvedUrl("favicon-candidates-gray.html"), size: 16, value: 16 },
+ { tag: "candidate 17x17", url: Qt.resolvedUrl("favicon-candidates-gray.html"), size: 17, value: 32 },
+ { tag: "candidate 31x31", url: Qt.resolvedUrl("favicon-candidates-gray.html"), size: 31, value: 32 },
+ { tag: "candidate 32x32", url: Qt.resolvedUrl("favicon-candidates-gray.html"), size: 32, value: 32 },
+ { tag: "candidate 33x33", url: Qt.resolvedUrl("favicon-candidates-gray.html"), size: 33, value: 64 },
+ { tag: "candidate 64x64", url: Qt.resolvedUrl("favicon-candidates-gray.html"), size: 64, value: 64 },
+ { tag: "candidate 128x128", url: Qt.resolvedUrl("favicon-candidates-gray.html"), size: 128, value: 128 },
+ { tag: "candidate 255x255", url: Qt.resolvedUrl("favicon-candidates-gray.html"), size: 255, value: 255 },
+ { tag: "candidate 256x256", url: Qt.resolvedUrl("favicon-candidates-gray.html"), size: 256, value: 255 },
];
}
@@ -287,8 +297,7 @@ TestWebEngineView {
compare(iconChangedSpy.count, 0)
- var url = Qt.resolvedUrl("favicon-multi-gray.html")
- webEngineView.url = url
+ webEngineView.url = row.url
verify(webEngineView.waitForLoadSucceeded())
iconChangedSpy.wait()
diff --git a/tests/auto/quick/qmltests/qmltests.pro b/tests/auto/quick/qmltests/qmltests.pro
index b8f0f7df1..64f7414ce 100644
--- a/tests/auto/quick/qmltests/qmltests.pro
+++ b/tests/auto/quick/qmltests/qmltests.pro
@@ -16,6 +16,7 @@ OTHER_FILES += \
$$PWD/data/directoryupload.html \
$$PWD/data/favicon.html \
$$PWD/data/favicon2.html \
+ $$PWD/data/favicon-candidates-gray.html \
$$PWD/data/favicon-misc.html \
$$PWD/data/favicon-multi.html \
$$PWD/data/favicon-multi-gray.html \
@@ -65,6 +66,11 @@ OTHER_FILES += \
$$PWD/data/tst_settings.qml \
$$PWD/data/tst_keyboardModifierMapping.qml \
$$PWD/data/icons/favicon.png \
+ $$PWD/data/icons/gray128.png \
+ $$PWD/data/icons/gray16.png \
+ $$PWD/data/icons/gray255.png \
+ $$PWD/data/icons/gray32.png \
+ $$PWD/data/icons/gray64.png \
$$PWD/data/icons/grayicons.ico \
$$PWD/data/icons/small-favicon.png \
$$PWD/data/icons/qt144.png \
diff --git a/tests/auto/widgets/qwebenginefaviconmanager/tst_qwebenginefaviconmanager.cpp b/tests/auto/widgets/qwebenginefaviconmanager/tst_qwebenginefaviconmanager.cpp
index b9ce0c33b..38311cad2 100644
--- a/tests/auto/widgets/qwebenginefaviconmanager/tst_qwebenginefaviconmanager.cpp
+++ b/tests/auto/widgets/qwebenginefaviconmanager/tst_qwebenginefaviconmanager.cpp
@@ -55,6 +55,7 @@ private Q_SLOTS:
void bestFavicon();
void touchIcon();
void multiIcon();
+ void candidateIcon();
void downloadIconsDisabled_data();
void downloadIconsDisabled();
void downloadTouchIconsEnabled_data();
@@ -323,9 +324,8 @@ void tst_QWebEngineFaviconManager::bestFavicon()
icon = m_page->icon();
QVERIFY(!icon.isNull());
- QCOMPARE(icon.availableSizes().count(), 1);
- iconSize = icon.availableSizes().first();
- QCOMPARE(iconSize, QSize(144, 144));
+ QVERIFY(icon.availableSizes().count() >= 1);
+ QVERIFY(icon.availableSizes().contains(QSize(144, 144)));
}
void tst_QWebEngineFaviconManager::touchIcon()
@@ -376,6 +376,33 @@ void tst_QWebEngineFaviconManager::multiIcon()
QVERIFY(icon.availableSizes().contains(QSize(64, 64)));
}
+void tst_QWebEngineFaviconManager::candidateIcon()
+{
+ if (!QDir(TESTS_SOURCE_DIR).exists())
+ W_QSKIP(QString("This test requires access to resources found in '%1'").arg(TESTS_SOURCE_DIR).toLatin1().constData(), SkipAll);
+
+ QSignalSpy loadFinishedSpy(m_page, SIGNAL(loadFinished(bool)));
+ QSignalSpy iconUrlChangedSpy(m_page, SIGNAL(iconUrlChanged(QUrl)));
+ QSignalSpy iconChangedSpy(m_page, SIGNAL(iconChanged(QIcon)));
+
+ QUrl url = QUrl::fromLocalFile(TESTS_SOURCE_DIR + QLatin1String("qwebenginefaviconmanager/resources/favicon-shortcut.html"));
+ m_page->load(url);
+
+ QTRY_COMPARE(loadFinishedSpy.count(), 1);
+ QTRY_COMPARE(iconUrlChangedSpy.count(), 1);
+ QTRY_COMPARE(iconChangedSpy.count(), 1);
+
+ QUrl iconUrl = iconUrlChangedSpy.at(0).at(0).toString();
+ QCOMPARE(m_page->iconUrl(), iconUrl);
+ QCOMPARE(iconUrl, QUrl::fromLocalFile(TESTS_SOURCE_DIR + QLatin1String("qwebenginefaviconmanager/resources/icons/qt144.png")));
+
+ const QIcon &icon = m_page->icon();
+ QVERIFY(!icon.isNull());
+ QCOMPARE(icon.availableSizes().count(), 2);
+ QVERIFY(icon.availableSizes().contains(QSize(32, 32)));
+ QVERIFY(icon.availableSizes().contains(QSize(144, 144)));
+}
+
void tst_QWebEngineFaviconManager::downloadIconsDisabled_data()
{
QTest::addColumn<QUrl>("url");
@@ -442,9 +469,8 @@ void tst_QWebEngineFaviconManager::downloadTouchIconsEnabled()
const QIcon &icon = m_page->icon();
QVERIFY(!icon.isNull());
- QCOMPARE(icon.availableSizes().count(), 1);
- QSize iconSize = icon.availableSizes().first();
- QCOMPARE(iconSize, expectedIconSize);
+ QVERIFY(icon.availableSizes().count() >= 1);
+ QVERIFY(icon.availableSizes().contains(expectedIconSize));
}
QTEST_MAIN(tst_QWebEngineFaviconManager)
diff --git a/tests/auto/widgets/qwebenginespellcheck/dict/en-US.aff b/tests/auto/widgets/qwebenginespellcheck/dict/en-US.aff
new file mode 100644
index 000000000..ff8185771
--- /dev/null
+++ b/tests/auto/widgets/qwebenginespellcheck/dict/en-US.aff
@@ -0,0 +1,5 @@
+SET UTF-8
+TRY esianrtolcdugmphbyfvkwzqESIANRTOLCDUGMPHBYFVKWZQ
+
+PFX Q Y 1
+PFX Q 0 q .
diff --git a/tests/auto/widgets/qwebenginespellcheck/dict/en-US.dic b/tests/auto/widgets/qwebenginespellcheck/dict/en-US.dic
new file mode 100644
index 000000000..3d4ecdfa4
--- /dev/null
+++ b/tests/auto/widgets/qwebenginespellcheck/dict/en-US.dic
@@ -0,0 +1,11 @@
+10
+he/Q
+I/Q
+it/Q
+love/Q
+loves/Q
+qt/Q
+she/Q
+they/Q
+we/Q
+you/Q
diff --git a/tests/auto/widgets/qwebenginespellcheck/qwebenginespellcheck.pro b/tests/auto/widgets/qwebenginespellcheck/qwebenginespellcheck.pro
new file mode 100644
index 000000000..437aad937
--- /dev/null
+++ b/tests/auto/widgets/qwebenginespellcheck/qwebenginespellcheck.pro
@@ -0,0 +1,22 @@
+include(../tests.pri)
+
+DISTFILES += \
+ dict/en-US.dic \
+ dict/en-US.aff
+
+qtPrepareTool(CONVERT_TOOL, qwebengine_convert_dict)
+
+debug_and_release {
+ CONFIG(debug, debug|release): DICTIONARIES_DIR = debug/qtwebengine_dictionaries
+ else: DICTIONARIES_DIR = release/qtwebengine_dictionaries
+} else {
+ DICTIONARIES_DIR = qtwebengine_dictionaries
+}
+
+dict.files = $$PWD/dict/en-US.dic
+dictoolbuild.input = dict.files
+dictoolbuild.output = $${DICTIONARIES_DIR}/${QMAKE_FILE_BASE}.bdic
+dictoolbuild.commands = $${CONVERT_TOOL} ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT}
+dictoolbuild.name = Build ${QMAKE_FILE_IN_BASE}
+dictoolbuild.CONFIG = no_link target_predeps
+QMAKE_EXTRA_COMPILERS += dictoolbuild
diff --git a/tests/auto/widgets/qwebenginespellcheck/resources/index.html b/tests/auto/widgets/qwebenginespellcheck/resources/index.html
new file mode 100644
index 000000000..520979244
--- /dev/null
+++ b/tests/auto/widgets/qwebenginespellcheck/resources/index.html
@@ -0,0 +1,36 @@
+<html>
+ <head>
+ <script type="text/javascript">
+ function makeEditable()
+ {
+ document.getElementsByClassName('textarea')[0].contentEditable = true;
+ }
+
+ function text()
+ {
+ return document.getElementsByClassName('textarea')[0].innerHTML;
+ }
+
+ function findWordPosition(text,word)
+ {
+ var divElement = document.getElementsByClassName('textarea')[0];
+ divElement.innerHTML = text;
+ var regex = new RegExp(word,'g');
+ divElement.innerHTML = divElement.innerHTML.replace(regex, '<span id="word">' + word + '</span>');
+ var spanElement = document.getElementById('word');
+ var rect = spanElement.getBoundingClientRect();
+ var array = new Array();
+ array.push(rect.left);
+ array.push(rect.top);
+ array.push(rect.right - rect.left);
+ array.push(rect.bottom - rect.top);
+ divElement.innerHTML = "";
+ return array;
+ }
+ </script>
+ </head>
+ <body>
+ <div class="textarea" style="width:300px; height:200px; border: 1px solid #ccc"></div>
+ </body>
+</html>
+
diff --git a/tests/auto/widgets/qwebenginespellcheck/tst_qwebenginespellcheck.cpp b/tests/auto/widgets/qwebenginespellcheck/tst_qwebenginespellcheck.cpp
new file mode 100644
index 000000000..2dfe3305d
--- /dev/null
+++ b/tests/auto/widgets/qwebenginespellcheck/tst_qwebenginespellcheck.cpp
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "util.h"
+#include <QtTest/QtTest>
+#include <QtWebEngineWidgets/qwebenginecontextmenudata.h>
+#include <QtWebEngineWidgets/qwebengineprofile.h>
+#include <QtWebEngineWidgets/qwebenginepage.h>
+#include <QtWebEngineWidgets/qwebengineview.h>
+
+class WebView : public QWebEngineView
+{
+ Q_OBJECT
+public:
+ void activateMenu(const QPoint &position)
+ {
+ QTest::mouseMove(focusWidget(), position);
+ QTest::mousePress(focusWidget(), Qt::RightButton, 0, position);
+ QContextMenuEvent evcont(QContextMenuEvent::Mouse, position, mapToGlobal(position));
+ event(&evcont);
+ }
+
+ const QWebEngineContextMenuData& data()
+ {
+ return m_data;
+ }
+
+signals:
+ void menuReady();
+
+protected:
+ void contextMenuEvent(QContextMenuEvent *)
+ {
+ m_data = page()->contextMenuData();
+ emit menuReady();
+ }
+private:
+ QWebEngineContextMenuData m_data;
+};
+
+class tst_QWebEngineSpellcheck : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void init();
+ void cleanup();
+ void initTestCase();
+ void spellCheckLanguage();
+ void spellCheckEnabled();
+ void spellcheck();
+
+private:
+ void load();
+ WebView *m_view;
+};
+
+void tst_QWebEngineSpellcheck::initTestCase()
+{
+ QWebEngineProfile *profile = QWebEngineProfile::defaultProfile();
+ QVERIFY(profile);
+ QVERIFY(!profile->isSpellCheckEnabled());
+ QVERIFY(profile->spellCheckLanguage().isEmpty());
+}
+
+void tst_QWebEngineSpellcheck::init()
+{
+ QWebEngineProfile *profile = QWebEngineProfile::defaultProfile();
+ profile->setSpellCheckEnabled(false);
+ profile->setSpellCheckLanguage(QString::null);
+ m_view = new WebView();
+}
+
+void tst_QWebEngineSpellcheck::load()
+{
+ m_view->page()->load(QUrl("qrc:///resources/index.html"));
+ m_view->show();
+ waitForSignal(m_view->page(), SIGNAL(loadFinished(bool)));
+}
+
+void tst_QWebEngineSpellcheck::cleanup()
+{
+ delete m_view;
+}
+
+void tst_QWebEngineSpellcheck::spellCheckLanguage()
+{
+ QWebEngineProfile *profile = QWebEngineProfile::defaultProfile();
+ QVERIFY(profile);
+ profile->setSpellCheckLanguage("en-US");
+ QVERIFY(profile->spellCheckLanguage() == "en-US");
+}
+
+void tst_QWebEngineSpellcheck::spellCheckEnabled()
+{
+ QWebEngineProfile *profile = QWebEngineProfile::defaultProfile();
+ QVERIFY(profile);
+ profile->setSpellCheckEnabled(true);
+ QVERIFY(profile->isSpellCheckEnabled());
+}
+
+void tst_QWebEngineSpellcheck::spellcheck()
+{
+ QWebEngineProfile *profile = QWebEngineProfile::defaultProfile();
+ QVERIFY(profile);
+ profile->setSpellCheckLanguage("en-US");
+ profile->setSpellCheckEnabled(true);
+ load();
+
+ // make textarea editable
+ evaluateJavaScriptSync(m_view->page(), "makeEditable();");
+
+ // calcuate position of misspelled word
+ QVariantList list = evaluateJavaScriptSync(m_view->page(), "findWordPosition('I lovee Qt ....','lovee');").toList();
+ QRect rect(list[0].value<int>(),list[1].value<int>(),list[2].value<int>(),list[3].value<int>());
+
+ //type text, spellchecker needs time
+ QTest::mouseMove(m_view->focusWidget(), QPoint(20,20));
+ QTest::mousePress(m_view->focusWidget(), Qt::LeftButton, 0, QPoint(20,20));
+ QString text("I lovee Qt ....");
+ for (int i = 0; i < text.length(); i++) {
+ QTest::keyClicks(m_view->focusWidget(), text.at(i));
+ QTest::qWait(60);
+ }
+
+ // make sure text is there
+ QString result = evaluateJavaScriptSync(m_view->page(), "text();").toString();
+ QVERIFY(result == text);
+
+ // open menu on misspelled word
+ m_view->activateMenu(rect.center());
+ waitForSignal(m_view, SIGNAL(menuReady()));
+
+ // check if menu is valid
+ QVERIFY(m_view->data().isValid());
+ QVERIFY(m_view->data().isContentEditable());
+
+ // check misspelled word
+ QVERIFY(m_view->data().misspelledWord() == "lovee");
+
+ // check suggestions
+ QStringList expected {"love", "loves"};
+ QVERIFY(m_view->data().spellCheckerSuggestions() == expected);
+
+ // check replace word
+ m_view->page()->replaceMisspelledWord("love");
+ text = "I love Qt ....";
+ result = evaluateJavaScriptSync(m_view->page(), "text();").toString();
+ QVERIFY(result == text);
+}
+
+QTEST_MAIN(tst_QWebEngineSpellcheck)
+#include "tst_qwebenginespellcheck.moc"
diff --git a/tests/auto/widgets/qwebenginespellcheck/tst_qwebenginespellcheck.qrc b/tests/auto/widgets/qwebenginespellcheck/tst_qwebenginespellcheck.qrc
new file mode 100644
index 000000000..505b932c7
--- /dev/null
+++ b/tests/auto/widgets/qwebenginespellcheck/tst_qwebenginespellcheck.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>resources/index.html</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/widgets/widgets.pro b/tests/auto/widgets/widgets.pro
index 6c516b38f..7543a4382 100644
--- a/tests/auto/widgets/widgets.pro
+++ b/tests/auto/widgets/widgets.pro
@@ -13,6 +13,11 @@ SUBDIRS += \
qwebenginesettings \
qwebengineview
+# QTBUG-53135, osx does not use hunspell
+!contains(WEBENGINE_CONFIG, no_spellcheck):!osx:!cross_compile {
+ SUBDIRS += qwebenginespellcheck
+}
+
qtHaveModule(positioning) {
SUBDIRS += positionplugin
qwebenginepage.depends = positionplugin
diff --git a/tools/qmake/mkspecs/features/configure.prf b/tools/qmake/mkspecs/features/configure.prf
index 0dfb67a84..679b282b3 100644
--- a/tools/qmake/mkspecs/features/configure.prf
+++ b/tools/qmake/mkspecs/features/configure.prf
@@ -64,6 +64,9 @@ defineTest(runConfigure) {
}
}
+ # Spellcheck support is moved to dev
+ WEBENGINE_CONFIG += no_spellcheck
+
isEmpty(skipBuildReason): {
cache(CONFIG, add, $$list(webengine_successfully_configured))
!isEmpty(WEBENGINE_CONFIG) {
@@ -71,6 +74,7 @@ defineTest(runConfigure) {
export(WEBENGINE_CONFIG)
}
}
+
}
# This is called from default_post, at which point we've also parsed
diff --git a/tools/qmake/mkspecs/features/default_pre.prf b/tools/qmake/mkspecs/features/default_pre.prf
index cb0625c2e..27aded013 100644
--- a/tools/qmake/mkspecs/features/default_pre.prf
+++ b/tools/qmake/mkspecs/features/default_pre.prf
@@ -4,7 +4,17 @@ QTWEBENGINE_ROOT = $$replace(PWD, /tools/qmake/mkspecs/features$,)
# We depend on libc++ to build chromium so our macosx-version-min has to be 10.7
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7
-QTWEBENGINEPROCESS_NAME = QtWebEngineProcess
+QTWEBENGINEPROCESS_NAME_RELEASE = QtWebEngineProcess
+debug_and_release {
+ QTWEBENGINEPROCESS_NAME_DEBUG = $$join(QTWEBENGINEPROCESS_NAME_RELEASE,,,d)
+} else {
+ QTWEBENGINEPROCESS_NAME_DEBUG = $$QTWEBENGINEPROCESS_NAME_RELEASE
+}
+build_pass:CONFIG(debug, debug|release) {
+ QTWEBENGINEPROCESS_NAME = $$QTWEBENGINEPROCESS_NAME_DEBUG
+} else {
+ QTWEBENGINEPROCESS_NAME = $$QTWEBENGINEPROCESS_NAME_RELEASE
+}
# Location of sync.profile
MODULE_BASE_DIR = $$QTWEBENGINE_ROOT