diff options
-rw-r--r-- | examples/webenginewidgets/demobrowser/browserapplication.cpp | 29 | ||||
-rw-r--r-- | examples/webenginewidgets/demobrowser/browserapplication.h | 1 | ||||
-rw-r--r-- | examples/webenginewidgets/demobrowser/edittreeview.cpp | 7 | ||||
-rw-r--r-- | examples/webenginewidgets/demobrowser/history.cpp | 99 | ||||
-rw-r--r-- | examples/webenginewidgets/demobrowser/history.h | 13 | ||||
-rw-r--r-- | examples/webenginewidgets/demobrowser/tabwidget.cpp | 3 | ||||
-rw-r--r-- | src/core/api/qtwebenginecoreglobal.cpp | 2 | ||||
-rw-r--r-- | src/core/browser_context_adapter.cpp | 2 | ||||
-rw-r--r-- | src/core/network_delegate_qt.cpp | 3 | ||||
-rw-r--r-- | src/core/url_request_context_getter_qt.cpp | 171 | ||||
-rw-r--r-- | src/core/url_request_context_getter_qt.h | 39 | ||||
-rw-r--r-- | src/core/web_contents_adapter.cpp | 1 | ||||
-rw-r--r-- | src/webengine/doc/src/qtwebengine-platform-notes.qdoc | 60 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebengineview.cpp | 1 |
14 files changed, 315 insertions, 116 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/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 fe667c570..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) 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/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/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/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()); } |