diff options
Diffstat (limited to 'src/core')
259 files changed, 8219 insertions, 11254 deletions
diff --git a/src/core/accessibility_activation_observer.cpp b/src/core/accessibility_activation_observer.cpp index 75ad90c54..b9d73cb68 100644 --- a/src/core/accessibility_activation_observer.cpp +++ b/src/core/accessibility_activation_observer.cpp @@ -39,7 +39,7 @@ #include "accessibility_activation_observer.h" -#ifndef QT_NO_ACCESSIBILITY +#if QT_CONFIG(accessibility) #include "content/browser/accessibility/browser_accessibility_state_impl.h" @@ -48,12 +48,13 @@ namespace QtWebEngineCore { namespace { bool isAccessibilityEnabled() { - // On Linux accessibility is disabled by default due to performance issues, - // and can be re-enabled by setting the QTWEBENGINE_ENABLE_LINUX_ACCESSIBILITY environment - // variable. For details, see QTBUG-59922. + // On Linux accessibility can be disabled due to performance issues by setting the + // QTWEBENGINE_ENABLE_LINUX_ACCESSIBILITY environment variable to 0. For details, + // see QTBUG-59922. #ifdef Q_OS_LINUX static bool accessibility_enabled - = qEnvironmentVariableIsSet("QTWEBENGINE_ENABLE_LINUX_ACCESSIBILITY"); + = qEnvironmentVariable("QTWEBENGINE_ENABLE_LINUX_ACCESSIBILITY", QLatin1String("1")) + == QLatin1String("1"); #else const bool accessibility_enabled = true; #endif @@ -86,4 +87,4 @@ void AccessibilityActivationObserver::accessibilityActiveChanged(bool active) } // namespace QtWebEngineCore -#endif // QT_NO_ACCESSIBILITY +#endif // QT_CONFIG(accessibility) diff --git a/src/core/accessibility_activation_observer.h b/src/core/accessibility_activation_observer.h index e42c83eb5..23fd2101e 100644 --- a/src/core/accessibility_activation_observer.h +++ b/src/core/accessibility_activation_observer.h @@ -40,9 +40,10 @@ #ifndef ACCESSIBILITY_ACTIVATION_OBSERVER_H #define ACCESSIBILITY_ACTIVATION_OBSERVER_H -#ifndef QT_NO_ACCESSIBILITY #include <QtGui/qaccessible.h> +#if QT_CONFIG(accessibility) + namespace QtWebEngineCore { class RenderWidgetHostViewQt; @@ -58,6 +59,6 @@ public: } // namespace QtWebEngineCore -#endif // QT_NO_ACCESSIBILITY +#endif // QT_CONFIG(accessibility) #endif // ACCESSIBILITY_ACTIVATION_OBSERVER_H diff --git a/src/core/accessibility_tree_formatter_qt.cpp b/src/core/accessibility_tree_formatter_qt.cpp index 3520087ae..51d33534b 100644 --- a/src/core/accessibility_tree_formatter_qt.cpp +++ b/src/core/accessibility_tree_formatter_qt.cpp @@ -37,7 +37,7 @@ ** ****************************************************************************/ -#include "content/browser/accessibility/accessibility_tree_formatter_browser.h" +#include "content/browser/accessibility/accessibility_tree_formatter_base.h" #include <utility> @@ -52,20 +52,27 @@ namespace content { -#ifndef QT_NO_ACCESSIBILITY -class AccessibilityTreeFormatterQt : public AccessibilityTreeFormatterBrowser { +#if QT_CONFIG(accessibility) +class AccessibilityTreeFormatterQt : public AccessibilityTreeFormatterBase { public: explicit AccessibilityTreeFormatterQt(); ~AccessibilityTreeFormatterQt() override; + std::unique_ptr<base::DictionaryValue> BuildAccessibilityTreeForSelector(const content::AccessibilityTreeFormatter::TreeSelector &) + { return nullptr; } + std::unique_ptr<base::DictionaryValue> BuildAccessibilityTreeForWindow(gfx::AcceleratedWidget) override { return nullptr; } + std::unique_ptr<base::DictionaryValue> BuildAccessibilityTree(content::BrowserAccessibility *) override; + private: - const base::FilePath::StringType GetExpectedFileSuffix() override; + base::FilePath::StringType GetExpectedFileSuffix() override; const std::string GetAllowEmptyString() override; const std::string GetAllowString() override; const std::string GetDenyString() override; const std::string GetDenyNodeString() override; - void AddProperties(const BrowserAccessibility &node, base::DictionaryValue* dict) override; - base::string16 ProcessTreeForOutput(const base::DictionaryValue &node, base::DictionaryValue * = nullptr) override; + const std::string GetRunUntilEventString() override; + void RecursiveBuildAccessibilityTree(const content::BrowserAccessibility &node, base::DictionaryValue *dict) const; + void AddProperties(const BrowserAccessibility &node, base::DictionaryValue *dict) const; + std::string ProcessTreeForOutput(const base::DictionaryValue &node, base::DictionaryValue * = nullptr) override; }; AccessibilityTreeFormatterQt::AccessibilityTreeFormatterQt() @@ -76,7 +83,30 @@ AccessibilityTreeFormatterQt::~AccessibilityTreeFormatterQt() { } -void AccessibilityTreeFormatterQt::AddProperties(const BrowserAccessibility &node, base::DictionaryValue *dict) +std::unique_ptr<base::DictionaryValue> AccessibilityTreeFormatterQt::BuildAccessibilityTree(content::BrowserAccessibility *root) +{ + std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue); + RecursiveBuildAccessibilityTree(*root, dict.get()); + return dict; +} + +void AccessibilityTreeFormatterQt::RecursiveBuildAccessibilityTree(const BrowserAccessibility &node, base::DictionaryValue *dict) const +{ + AddProperties(node, dict); + + auto children = std::make_unique<base::ListValue>(); + for (size_t i = 0; i < node.PlatformChildCount(); ++i) { + std::unique_ptr<base::DictionaryValue> child_dict(new base::DictionaryValue); + + content::BrowserAccessibility *child_node = node.PlatformGetChild(i); + + RecursiveBuildAccessibilityTree(*child_node, child_dict.get()); + children->Append(std::move(child_dict)); + } + dict->Set(kChildrenDictAttr, std::move(children)); +} + +void AccessibilityTreeFormatterQt::AddProperties(const BrowserAccessibility &node, base::DictionaryValue *dict) const { dict->SetInteger("id", node.GetId()); const BrowserAccessibilityQt *acc_node = ToBrowserAccessibilityQt(&node); @@ -142,13 +172,13 @@ void AccessibilityTreeFormatterQt::AddProperties(const BrowserAccessibility &nod dict->SetString("description", acc_node->text(QAccessible::Description).toStdString()); } -base::string16 AccessibilityTreeFormatterQt::ProcessTreeForOutput(const base::DictionaryValue &node, base::DictionaryValue *) +std::string AccessibilityTreeFormatterQt::ProcessTreeForOutput(const base::DictionaryValue &node, base::DictionaryValue *) { - base::string16 error_value; + std::string error_value; if (node.GetString("error", &error_value)) return error_value; - base::string16 line; + std::string line; std::string role_value; node.GetString("role", &role_value); if (!role_value.empty()) @@ -176,10 +206,10 @@ base::string16 AccessibilityTreeFormatterQt::ProcessTreeForOutput(const base::Di node.GetInteger("id", &id_value); WriteAttribute(false, base::StringPrintf("id=%d", id_value), &line); - return line + base::ASCIIToUTF16("\n"); + return line + "\n"; } -const base::FilePath::StringType AccessibilityTreeFormatterQt::GetExpectedFileSuffix() +base::FilePath::StringType AccessibilityTreeFormatterQt::GetExpectedFileSuffix() { return FILE_PATH_LITERAL("-expected-qt.txt"); } @@ -204,12 +234,17 @@ const std::string AccessibilityTreeFormatterQt::GetDenyNodeString() return "@QT-DENY-NODE:"; } -#endif // QT_NO_ACCESSIBILITY +const std::string AccessibilityTreeFormatterQt::GetRunUntilEventString() +{ + return "@QT-RUN-UNTIL-EVENT:"; +} + +#endif // QT_CONFIG(accessibility) // static std::unique_ptr<AccessibilityTreeFormatter> AccessibilityTreeFormatter::Create() { -#ifndef QT_NO_ACCESSIBILITY +#if QT_CONFIG(accessibility) return std::unique_ptr<AccessibilityTreeFormatter>(new AccessibilityTreeFormatterQt()); #else return nullptr; diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro index 5e8b8387e..28d5586ba 100644 --- a/src/core/api/core_api.pro +++ b/src/core/api/core_api.pro @@ -14,7 +14,8 @@ CONFIG -= create_prl # Copy this logic from qt_module.prf so that the intermediate library can be # created to the same rules as the final module linking in core_module.pro. !host_build:if(win32|mac):!macx-xcode { - qtConfig(debug_and_release): CONFIG += debug_and_release build_all + qtConfig(debug_and_release): CONFIG += debug_and_release + qtConfig(build_all): CONFIG += build_all } DEFINES += \ @@ -22,9 +23,15 @@ DEFINES += \ NOMINMAX CHROMIUM_SRC_DIR = $$QTWEBENGINE_ROOT/$$getChromiumSrcDir() -CHROMIUM_GEN_DIR = $$OUT_PWD/../$$getConfigDir()/gen + +isUniversal() { + CHROMIUM_GEN_DIR = $$OUT_PWD/../$$QT_ARCH/$$getConfigDir()/gen +} else { + CHROMIUM_GEN_DIR = $$OUT_PWD/../$$getConfigDir()/gen +} INCLUDEPATH += $$QTWEBENGINE_ROOT/src/core \ $$CHROMIUM_GEN_DIR \ + $$CHROMIUM_SRC_DIR/third_party/abseil-cpp \ $$CHROMIUM_SRC_DIR gcc: QMAKE_CXXFLAGS_WARN_ON = -Wno-unused-parameter @@ -67,11 +74,13 @@ SOURCES = \ ### Qt6 Remove this workaround unix:!isEmpty(QMAKE_LFLAGS_VERSION_SCRIPT):!static { - CONFIG -= warning_clean SOURCES += qtbug-60565.cpp \ qtbug-61521.cpp } +# Chromium headers included are not remotely clean +CONFIG -= warning_clean + msvc { # Create a list of object files that can be used as response file for the linker. # This is done to simulate -whole-archive on MSVC. diff --git a/src/core/api/qtwebenginecoreglobal.cpp b/src/core/api/qtwebenginecoreglobal.cpp index 9e2a4a5b1..f51aa25c3 100644 --- a/src/core/api/qtwebenginecoreglobal.cpp +++ b/src/core/api/qtwebenginecoreglobal.cpp @@ -40,23 +40,26 @@ #include "qtwebenginecoreglobal_p.h" #include <QGuiApplication> -#ifndef QT_NO_OPENGL +#if QT_CONFIG(opengl) # include <QOpenGLContext> #ifdef Q_OS_MACOS #include <sys/types.h> #include <sys/sysctl.h> +#include <QOffscreenSurface> +#include "macos_context_type_helper.h" #endif #endif #include <QThread> +#include "web_engine_context.h" -#ifndef QT_NO_OPENGL +#if QT_CONFIG(opengl) QT_BEGIN_NAMESPACE Q_GUI_EXPORT void qt_gl_set_global_share_context(QOpenGLContext *context); Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context(); QT_END_NAMESPACE #endif -#ifndef QT_NO_OPENGL +#if QT_CONFIG(opengl) #ifdef Q_OS_MACOS static bool needsOfflineRendererWorkaround() { @@ -75,7 +78,7 @@ static bool needsOfflineRendererWorkaround() #endif namespace QtWebEngineCore { -#ifndef QT_NO_OPENGL +#if QT_CONFIG(opengl) static QOpenGLContext *shareContext; static void deleteShareContext() @@ -94,7 +97,7 @@ static void deleteShareContext() Q_WEBENGINECORE_PRIVATE_EXPORT void initialize() { -#ifndef QT_NO_OPENGL +#if QT_CONFIG(opengl) #ifdef Q_OS_WIN32 qputenv("QT_D3DCREATE_MULTITHREADED", "1"); #endif @@ -127,6 +130,52 @@ Q_WEBENGINECORE_PRIVATE_EXPORT void initialize() shareContext = new QOpenGLContext; QSurfaceFormat format = QSurfaceFormat::defaultFormat(); // format.setOption(QSurfaceFormat::ResetNotification); + +#ifdef Q_OS_MACOS + if (format == QSurfaceFormat()) { + QOpenGLContext testContext; + + // Chromium turns off OpenGL for CoreProfiles with versions < 4.1 + // The newest Mac that only supports 3.3 was released in Mid 2011, + // so it should be safe to request 4.1, but we still double check it + // works in order not to set an invalid default surface format. + format.setVersion(4, 1); + format.setProfile(QSurfaceFormat::CoreProfile); + + testContext.setFormat(format); + if (testContext.create()) { + QOffscreenSurface surface; + surface.setFormat(format); + surface.create(); + + if (testContext.makeCurrent(&surface)) { + // The Cocoa QPA integration allows sharing between OpenGL 3.2 and 4.1 contexts, + // which means even though we requested a 4.1 context, if we only get a 3.2 context, + // it will still work an Chromium will not black list it. + if (testContext.format().version() >= qMakePair(3, 2) && + testContext.format().profile() == QSurfaceFormat::CoreProfile && + !isCurrentContextSoftware()) { + QSurfaceFormat::setDefaultFormat(format); + } else { + qWarning("The available OpenGL surface format was either not version 3.2 or higher or not a Core Profile.\n" + "Chromium on macOS will fall back to software rendering in this case.\n" + "Hardware acceleration and features such as WebGL will not be available."); + format = QSurfaceFormat::defaultFormat(); + } + testContext.doneCurrent(); + } + surface.destroy(); + } + } else { + // The user explicitly requested a specific surface format that does not fit Chromium's requirements. Warn them about this. + if (format.version() < qMakePair(3,2) || format.profile() != QSurfaceFormat::CoreProfile) { + qWarning("An OpenGL surfcace format was requested that is either not version 3.2 or higher or a not Core Profile.\n" + "Chromium on macOS will fall back to software rendering in this case.\n" + "Hardware acceleration and features such as WebGL will not be available."); + } + } +#endif + shareContext->setFormat(format); shareContext->create(); qAddPostRoutine(deleteShareContext); @@ -134,6 +183,12 @@ Q_WEBENGINECORE_PRIVATE_EXPORT void initialize() // Classes like QOpenGLWidget check for the attribute app->setAttribute(Qt::AA_ShareOpenGLContexts); -#endif // QT_NO_OPENGL +#endif // QT_CONFIG(opengl) } + +bool closingDown() +{ + return WebEngineContext::closingDown(); +} + } // namespace QtWebEngineCore diff --git a/src/core/api/qtwebenginecoreglobal_p.h b/src/core/api/qtwebenginecoreglobal_p.h index 655b2a814..3a3496e04 100644 --- a/src/core/api/qtwebenginecoreglobal_p.h +++ b/src/core/api/qtwebenginecoreglobal_p.h @@ -65,4 +65,7 @@ #define Q_WEBENGINECORE_PRIVATE_EXPORT Q_WEBENGINECORE_EXPORT +namespace QtWebEngineCore { +Q_WEBENGINECORE_PRIVATE_EXPORT bool closingDown(); +} // namespace #endif // QTWEBENGINECOREGLOBAL_P_H diff --git a/src/core/api/qwebenginecookiestore.cpp b/src/core/api/qwebenginecookiestore.cpp index 40594b9c0..a09a74bf6 100644 --- a/src/core/api/qwebenginecookiestore.cpp +++ b/src/core/api/qwebenginecookiestore.cpp @@ -89,6 +89,9 @@ void QWebEngineCookieStorePrivate::processPendingUserCookies() delegate->deleteSessionCookies(CallbackDirectory::DeleteSessionCookiesCallbackId); } + if (bool(filterCallback)) + delegate->setHasFilter(true); + if (m_pendingUserCookies.isEmpty()) return; @@ -362,7 +365,10 @@ void QWebEngineCookieStore::deleteAllCookies() */ void QWebEngineCookieStore::setCookieFilter(const std::function<bool(const FilterRequest &)> &filterCallback) { + bool changed = bool(d_ptr->filterCallback) != bool(filterCallback); d_ptr->filterCallback = filterCallback; + if (changed && d_ptr->delegate) + d_ptr->delegate->setHasFilter(bool(d_ptr->filterCallback)); } /*! @@ -371,7 +377,10 @@ void QWebEngineCookieStore::setCookieFilter(const std::function<bool(const Filte */ void QWebEngineCookieStore::setCookieFilter(std::function<bool(const FilterRequest &)> &&filterCallback) { + bool changed = bool(d_ptr->filterCallback) != bool(filterCallback); d_ptr->filterCallback = std::move(filterCallback); + if (changed && d_ptr->delegate) + d_ptr->delegate->setHasFilter(bool(d_ptr->filterCallback)); } /*! diff --git a/src/core/api/qwebenginenotification.cpp b/src/core/api/qwebenginenotification.cpp index abc63fed2..0505b825a 100644 --- a/src/core/api/qwebenginenotification.cpp +++ b/src/core/api/qwebenginenotification.cpp @@ -132,7 +132,7 @@ bool QWebEngineNotification::matches(const QWebEngineNotification *other) const } /*! - \qmlproperty bool WebEngineNotification::title + \qmlproperty string WebEngineNotification::title \brief The title of the notification. */ /*! diff --git a/src/core/api/qwebengineurlrequestinfo.cpp b/src/core/api/qwebengineurlrequestinfo.cpp index e44410099..040305f66 100644 --- a/src/core/api/qwebengineurlrequestinfo.cpp +++ b/src/core/api/qwebengineurlrequestinfo.cpp @@ -40,34 +40,10 @@ #include "qwebengineurlrequestinfo.h" #include "qwebengineurlrequestinfo_p.h" -#include "content/public/common/resource_type.h" - #include "web_contents_adapter_client.h" QT_BEGIN_NAMESPACE -ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeMainFrame, content::ResourceType::kMainFrame) -ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeSubFrame, content::ResourceType::kSubFrame) -ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeStylesheet, content::ResourceType::kStylesheet) -ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeScript, content::ResourceType::kScript) -ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeImage, content::ResourceType::kImage) -ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeFontResource, content::ResourceType::kFontResource) -ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeSubResource, content::ResourceType::kSubResource) -ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeObject, content::ResourceType::kObject) -ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeMedia, content::ResourceType::kMedia) -ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeWorker, content::ResourceType::kWorker) -ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeSharedWorker, content::ResourceType::kSharedWorker) -ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypePrefetch, content::ResourceType::kPrefetch) -ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeFavicon, content::ResourceType::kFavicon) -ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeXhr, content::ResourceType::kXhr) -ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypePing, content::ResourceType::kPing) -ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeServiceWorker, content::ResourceType::kServiceWorker) -ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeCspReport, content::ResourceType::kCspReport) -ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypePluginResource, content::ResourceType::kPluginResource) -ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeNavigationPreloadMainFrame, content::ResourceType::kNavigationPreloadMainFrame) -ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeNavigationPreloadSubFrame, content::ResourceType::kNavigationPreloadSubFrame) -ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeLast, content::ResourceType::kMaxValue) - ASSERT_ENUMS_MATCH(QtWebEngineCore::WebContentsAdapterClient::LinkNavigation, QWebEngineUrlRequestInfo::NavigationTypeLink) ASSERT_ENUMS_MATCH(QtWebEngineCore::WebContentsAdapterClient::TypedNavigation, QWebEngineUrlRequestInfo::NavigationTypeTyped) ASSERT_ENUMS_MATCH(QtWebEngineCore::WebContentsAdapterClient::FormSubmittedNavigation, @@ -131,10 +107,12 @@ ASSERT_ENUMS_MATCH(QtWebEngineCore::WebContentsAdapterClient::RedirectNavigation QWebEngineUrlRequestInfoPrivate::QWebEngineUrlRequestInfoPrivate(QWebEngineUrlRequestInfo::ResourceType resource, QWebEngineUrlRequestInfo::NavigationType navigation, - const QUrl &u, const QUrl &fpu, const QUrl &i, const QByteArray &m) + const QUrl &u, const QUrl &fpu, const QUrl &i, + const QByteArray &m) : resourceType(resource) , navigationType(navigation) , shouldBlockRequest(false) + , shouldRedirectRequest(false) , url(u) , firstPartyUrl(fpu) , initiator(i) @@ -145,11 +123,25 @@ QWebEngineUrlRequestInfoPrivate::QWebEngineUrlRequestInfoPrivate(QWebEngineUrlRe /*! \internal */ +QWebEngineUrlRequestInfo::QWebEngineUrlRequestInfo() {} + +/*! + \internal +*/ QWebEngineUrlRequestInfo::QWebEngineUrlRequestInfo(QWebEngineUrlRequestInfo &&p) : d_ptr(p.d_ptr.take()) {} /*! \internal */ +QWebEngineUrlRequestInfo &QWebEngineUrlRequestInfo::operator=(QWebEngineUrlRequestInfo &&p) +{ + d_ptr.reset(p.d_ptr.take()); + return *this; +} + +/*! + \internal +*/ QWebEngineUrlRequestInfo::~QWebEngineUrlRequestInfo() {} @@ -296,6 +288,7 @@ void QWebEngineUrlRequestInfo::redirect(const QUrl &url) { d_ptr->changed = true; d_ptr->url = url; + d_ptr->shouldRedirectRequest = true; } /*! diff --git a/src/core/api/qwebengineurlrequestinfo.h b/src/core/api/qwebengineurlrequestinfo.h index 69033cdfd..7c12f1861 100644 --- a/src/core/api/qwebengineurlrequestinfo.h +++ b/src/core/api/qwebengineurlrequestinfo.h @@ -47,8 +47,6 @@ namespace QtWebEngineCore { class InterceptedRequest; -class NetworkDelegateQt; -class URLRequestNotification; } // namespace QtWebEngineCore QT_BEGIN_NAMESPACE @@ -109,16 +107,16 @@ public: void setHttpHeader(const QByteArray &name, const QByteArray &value); private: - friend class QtWebEngineCore::NetworkDelegateQt; - friend class QtWebEngineCore::URLRequestNotification; friend class QtWebEngineCore::InterceptedRequest; Q_DISABLE_COPY(QWebEngineUrlRequestInfo) Q_DECLARE_PRIVATE(QWebEngineUrlRequestInfo) void resetChanged(); + QWebEngineUrlRequestInfo(); QWebEngineUrlRequestInfo(QWebEngineUrlRequestInfoPrivate *p); QWebEngineUrlRequestInfo(QWebEngineUrlRequestInfo &&p); + QWebEngineUrlRequestInfo &operator=(QWebEngineUrlRequestInfo &&p); ~QWebEngineUrlRequestInfo(); QScopedPointer<QWebEngineUrlRequestInfoPrivate> d_ptr; }; diff --git a/src/core/api/qwebengineurlrequestinfo_p.h b/src/core/api/qwebengineurlrequestinfo_p.h index 35b5610be..206104ec9 100644 --- a/src/core/api/qwebengineurlrequestinfo_p.h +++ b/src/core/api/qwebengineurlrequestinfo_p.h @@ -75,7 +75,7 @@ public: QWebEngineUrlRequestInfo::ResourceType resourceType; QWebEngineUrlRequestInfo::NavigationType navigationType; bool shouldBlockRequest; - + bool shouldRedirectRequest; QUrl url; QUrl firstPartyUrl; QUrl initiator; diff --git a/src/core/api/qwebengineurlschemehandler.h b/src/core/api/qwebengineurlschemehandler.h index 09c5b08cb..4574bf8b0 100644 --- a/src/core/api/qwebengineurlschemehandler.h +++ b/src/core/api/qwebengineurlschemehandler.h @@ -44,10 +44,6 @@ #include <QtCore/qobject.h> -namespace QtWebEngineCore { -class URLRequestContextGetterQt; -} - QT_BEGIN_NAMESPACE class QWebEngineUrlRequestJob; diff --git a/src/core/authentication_dialog_controller.cpp b/src/core/authentication_dialog_controller.cpp index 23dd62979..e37ffab44 100644 --- a/src/core/authentication_dialog_controller.cpp +++ b/src/core/authentication_dialog_controller.cpp @@ -53,11 +53,9 @@ AuthenticationDialogControllerPrivate::AuthenticationDialogControllerPrivate(bas void AuthenticationDialogControllerPrivate::dialogFinished(bool accepted, const QString &user, const QString &password) { - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&LoginDelegateQt::sendAuthToRequester, - loginDelegate, - accepted, user, password)); + base::PostTask(FROM_HERE, {content::BrowserThread::UI}, + base::BindOnce(&LoginDelegateQt::sendAuthToRequester, + loginDelegate, accepted, user, password)); } AuthenticationDialogController::AuthenticationDialogController(AuthenticationDialogControllerPrivate *dd) diff --git a/src/core/browser_accessibility_manager_qt.cpp b/src/core/browser_accessibility_manager_qt.cpp index 8e3ee5940..1d635a6e9 100644 --- a/src/core/browser_accessibility_manager_qt.cpp +++ b/src/core/browser_accessibility_manager_qt.cpp @@ -48,31 +48,29 @@ namespace content { BrowserAccessibilityManager* BrowserAccessibilityManager::Create( const ui::AXTreeUpdate& initialTree, - BrowserAccessibilityDelegate* delegate, - BrowserAccessibilityFactory* factory) + BrowserAccessibilityDelegate* delegate) { -#ifndef QT_NO_ACCESSIBILITY - return new BrowserAccessibilityManagerQt(nullptr, initialTree, delegate, factory); +#if QT_CONFIG(accessibility) + return new BrowserAccessibilityManagerQt(nullptr, initialTree, delegate); #else - delete factory; return nullptr; -#endif // QT_NO_ACCESSIBILITY +#endif // QT_CONFIG(accessibility) } BrowserAccessibility *BrowserAccessibility::Create() { -#ifndef QT_NO_ACCESSIBILITY +#if QT_CONFIG(accessibility) return new BrowserAccessibilityQt(); #else return nullptr; -#endif // QT_NO_ACCESSIBILITY +#endif // QT_CONFIG(accessibility) } -#ifndef QT_NO_ACCESSIBILITY +#if QT_CONFIG(accessibility) BrowserAccessibilityManagerQt::BrowserAccessibilityManagerQt( QObject *parentObject, const ui::AXTreeUpdate &initialTree, - BrowserAccessibilityDelegate* delegate, BrowserAccessibilityFactory* factory) - : BrowserAccessibilityManager(delegate, factory) + BrowserAccessibilityDelegate* delegate) + : BrowserAccessibilityManager(delegate) , m_parentObject(parentObject) { Initialize(initialTree); @@ -164,6 +162,6 @@ void BrowserAccessibilityManagerQt::FireGeneratedEvent(ui::AXEventGenerator::Eve } } -#endif // QT_NO_ACCESSIBILITY +#endif // QT_CONFIG(accessibility) } diff --git a/src/core/browser_accessibility_manager_qt.h b/src/core/browser_accessibility_manager_qt.h index 16e2d1fe7..600ad673c 100644 --- a/src/core/browser_accessibility_manager_qt.h +++ b/src/core/browser_accessibility_manager_qt.h @@ -41,8 +41,11 @@ #define BROWSER_ACCESSIBILITY_MANAGER_QT_H #include "content/browser/accessibility/browser_accessibility_manager.h" -#ifndef QT_NO_ACCESSIBILITY + #include <QtCore/qobject.h> +#include <QtGui/qtgui-config.h> + +#if QT_CONFIG(accessibility) QT_BEGIN_NAMESPACE class QAccessibleInterface; @@ -53,10 +56,9 @@ namespace content { class BrowserAccessibilityManagerQt : public BrowserAccessibilityManager { public: - BrowserAccessibilityManagerQt(QObject* parentObject, - const ui::AXTreeUpdate& initialTree, - BrowserAccessibilityDelegate* delegate, - BrowserAccessibilityFactory* factory = new BrowserAccessibilityFactory()); + BrowserAccessibilityManagerQt(QObject *parentObject, + const ui::AXTreeUpdate &initialTree, + BrowserAccessibilityDelegate *delegate); ~BrowserAccessibilityManagerQt() override; void FireBlinkEvent(ax::mojom::Event event_type, BrowserAccessibility* node) override; @@ -74,5 +76,5 @@ private: } -#endif // QT_NO_ACCESSIBILITY +#endif // QT_CONFIG(accessibility) #endif diff --git a/src/core/browser_accessibility_qt.cpp b/src/core/browser_accessibility_qt.cpp index c760dcd45..fabad0609 100644 --- a/src/core/browser_accessibility_qt.cpp +++ b/src/core/browser_accessibility_qt.cpp @@ -43,7 +43,7 @@ #include "browser_accessibility_qt.h" -#ifndef QT_NO_ACCESSIBILITY +#if QT_CONFIG(accessibility) #include "ui/accessibility/ax_enums.mojom.h" @@ -79,7 +79,7 @@ bool BrowserAccessibilityQt::isValid() const QObject *BrowserAccessibilityQt::object() const { - return 0; + return nullptr; } QAccessibleInterface *BrowserAccessibilityQt::childAt(int x, int y) const @@ -90,7 +90,7 @@ QAccessibleInterface *BrowserAccessibilityQt::childAt(int x, int y) const if (childIface->rect().contains(x,y)) return childIface; } - return 0; + return nullptr; } void *BrowserAccessibilityQt::interface_cast(QAccessible::InterfaceType type) @@ -132,7 +132,7 @@ void *BrowserAccessibilityQt::interface_cast(QAccessible::InterfaceType type) default: break; } - return 0; + return nullptr; } QAccessibleInterface *BrowserAccessibilityQt::parent() const @@ -148,6 +148,19 @@ QAccessibleInterface *BrowserAccessibilityQt::child(int index) const return static_cast<BrowserAccessibilityQt*>(BrowserAccessibility::PlatformGetChild(index)); } +QAccessibleInterface *BrowserAccessibilityQt::focusChild() const +{ + if (state().focused) + return const_cast<BrowserAccessibilityQt *>(this); + + for (int i = 0; i < childCount(); ++i) { + if (QAccessibleInterface *iface = child(i)->focusChild()) + return iface; + } + + return nullptr; +} + int BrowserAccessibilityQt::childCount() const { return PlatformChildCount(); @@ -196,6 +209,13 @@ QAccessible::Role BrowserAccessibilityQt::role() const case ax::mojom::Role::kUnknown: return QAccessible::NoRole; + // Internal roles (matching auralinux and win) + case ax::mojom::Role::kKeyboard: + case ax::mojom::Role::kIgnored: + case ax::mojom::Role::kImeCandidate: + case ax::mojom::Role::kPresentational: + return QAccessible::NoRole; + // Used by Chromium to distinguish between the root of the tree // for this page, and a web area for a frame within this page. case ax::mojom::Role::kWebArea: @@ -212,8 +232,6 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::AlertMessage; case ax::mojom::Role::kAnchor: return QAccessible::Link; - case ax::mojom::Role::kAnnotation: - return QAccessible::StaticText; case ax::mojom::Role::kApplication: return QAccessible::Document; // returning Application here makes Qt return the top level app object case ax::mojom::Role::kArticle: @@ -238,6 +256,8 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::CheckBox; case ax::mojom::Role::kClient: return QAccessible::Client; + case ax::mojom::Role::kCode: + return QAccessible::StaticText; case ax::mojom::Role::kColorWell: return QAccessible::ColorChooser; case ax::mojom::Role::kColumn: @@ -250,6 +270,8 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::ComboBox; case ax::mojom::Role::kComplementary: return QAccessible::ComplementaryContent; + case ax::mojom::Role::kComment: + return QAccessible::Section; case ax::mojom::Role::kContentDeletion: case ax::mojom::Role::kContentInsertion: return QAccessible::Grouping; @@ -269,17 +291,17 @@ QAccessible::Role BrowserAccessibilityQt::role() const case ax::mojom::Role::kDetails: return QAccessible::Grouping; case ax::mojom::Role::kDesktop: - return QAccessible::NoRole; // FIXME + return QAccessible::Pane; case ax::mojom::Role::kDialog: return QAccessible::Dialog; case ax::mojom::Role::kDirectory: - return QAccessible::NoRole; // FIXME + return QAccessible::List; case ax::mojom::Role::kDisclosureTriangle: - return QAccessible::NoRole; // FIXME + return QAccessible::Button; case ax::mojom::Role::kGenericContainer: return QAccessible::Section; case ax::mojom::Role::kDocCover: - return QAccessible::Graphic; + return QAccessible::Graphic; case ax::mojom::Role::kDocBackLink: case ax::mojom::Role::kDocBiblioRef: case ax::mojom::Role::kDocGlossRef: @@ -318,14 +340,18 @@ QAccessible::Role BrowserAccessibilityQt::role() const case ax::mojom::Role::kDocPrologue: case ax::mojom::Role::kDocPullquote: case ax::mojom::Role::kDocQna: + return QAccessible::Section; case ax::mojom::Role::kDocSubtitle: + return QAccessible::Heading; case ax::mojom::Role::kDocTip: case ax::mojom::Role::kDocToc: return QAccessible::Section; case ax::mojom::Role::kDocument: return QAccessible::Document; case ax::mojom::Role::kEmbeddedObject: - return QAccessible::Grouping; // FIXME + return QAccessible::Grouping; + case ax::mojom::Role::kEmphasis: + return QAccessible::StaticText; case ax::mojom::Role::kFeed: return QAccessible::Section; case ax::mojom::Role::kFigcaption: @@ -334,6 +360,8 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::Section; case ax::mojom::Role::kFooter: return QAccessible::Footer; + case ax::mojom::Role::kFooterAsNonLandmark: + return QAccessible::Section; case ax::mojom::Role::kForm: return QAccessible::Form; case ax::mojom::Role::kGraphicsDocument: @@ -346,32 +374,29 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::Table; case ax::mojom::Role::kGroup: return QAccessible::Grouping; + case ax::mojom::Role::kHeader: + case ax::mojom::Role::kHeaderAsNonLandmark: + return QAccessible::Section; case ax::mojom::Role::kHeading: return QAccessible::Heading; case ax::mojom::Role::kIframe: - return QAccessible::Grouping; + return QAccessible::WebDocument; case ax::mojom::Role::kIframePresentational: - return QAccessible::NoRole; // FIXME - case ax::mojom::Role::kIgnored: - return QAccessible::NoRole; + return QAccessible::Grouping; case ax::mojom::Role::kImage: return QAccessible::Graphic; case ax::mojom::Role::kImageMap: - return QAccessible::Graphic; + return QAccessible::Document; case ax::mojom::Role::kInlineTextBox: - return QAccessible::EditableText; + return QAccessible::StaticText; case ax::mojom::Role::kInputTime: return QAccessible::SpinBox; - case ax::mojom::Role::kKeyboard: - return QAccessible::NoRole; // FIXME case ax::mojom::Role::kLabelText: return QAccessible::StaticText; case ax::mojom::Role::kLayoutTable: case ax::mojom::Role::kLayoutTableCell: - case ax::mojom::Role::kLayoutTableColumn: case ax::mojom::Role::kLayoutTableRow: - // No role description. - return QAccessible::NoRole; + return QAccessible::Section; case ax::mojom::Role::kLegend: return QAccessible::StaticText; case ax::mojom::Role::kLineBreak: @@ -410,8 +435,6 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::CheckBox; case ax::mojom::Role::kMenuItemRadio: return QAccessible::RadioButton; - case ax::mojom::Role::kMenuButton: - return QAccessible::MenuItem; case ax::mojom::Role::kMenuListOption: return QAccessible::MenuItem; case ax::mojom::Role::kMenuListPopup: @@ -426,12 +449,16 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::Pane; case ax::mojom::Role::kParagraph: return QAccessible::Paragraph; + case ax::mojom::Role::kPdfActionableHighlight: + return QAccessible::Button; + case ax::mojom::Role::kPluginObject: + return QAccessible::Grouping; case ax::mojom::Role::kPopUpButton: return QAccessible::ComboBox; + case ax::mojom::Role::kPortal: + return QAccessible::Button; case ax::mojom::Role::kPre: return QAccessible::Section; - case ax::mojom::Role::kPresentational: - return QAccessible::NoRole; // FIXME case ax::mojom::Role::kProgressIndicator: return QAccessible::ProgressBar; case ax::mojom::Role::kRadioButton: @@ -442,22 +469,27 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::Section; case ax::mojom::Role::kRow: return QAccessible::Row; + case ax::mojom::Role::kRowGroup: + return QAccessible::Section; case ax::mojom::Role::kRowHeader: return QAccessible::RowHeader; case ax::mojom::Role::kRuby: return QAccessible::StaticText; + case ax::mojom::Role::kRubyAnnotation: + return QAccessible::StaticText; case ax::mojom::Role::kScrollBar: return QAccessible::ScrollBar; case ax::mojom::Role::kScrollView: - return QAccessible::NoRole; // FIXME + return QAccessible::Pane; case ax::mojom::Role::kSearch: return QAccessible::Section; case ax::mojom::Role::kSearchBox: return QAccessible::EditableText; + case ax::mojom::Role::kSection: + return QAccessible::Section; case ax::mojom::Role::kSlider: - return QAccessible::Slider; case ax::mojom::Role::kSliderThumb: - return QAccessible::NoRole; // FIXME + return QAccessible::Slider; case ax::mojom::Role::kSpinButton: return QAccessible::SpinBox; case ax::mojom::Role::kSplitter: @@ -466,6 +498,10 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::StaticText; case ax::mojom::Role::kStatus: return QAccessible::Indicator; + case ax::mojom::Role::kStrong: + return QAccessible::StaticText; + case ax::mojom::Role::kSuggestion: + return QAccessible::Section; case ax::mojom::Role::kSvgRoot: return QAccessible::Graphic; case ax::mojom::Role::kSwitch: @@ -479,7 +515,7 @@ QAccessible::Role BrowserAccessibilityQt::role() const case ax::mojom::Role::kTabList: return QAccessible::PageTabList; case ax::mojom::Role::kTabPanel: - return QAccessible::PageTab; + return QAccessible::Pane; case ax::mojom::Role::kTerm: return QAccessible::StaticText; case ax::mojom::Role::kTextField: @@ -488,7 +524,7 @@ QAccessible::Role BrowserAccessibilityQt::role() const case ax::mojom::Role::kTimer: return QAccessible::Clock; case ax::mojom::Role::kTitleBar: - return QAccessible::NoRole; // FIXME + return QAccessible::Document; case ax::mojom::Role::kToggleButton: return QAccessible::Button; case ax::mojom::Role::kToolbar: @@ -609,16 +645,7 @@ QAccessible::State BrowserAccessibilityQt::state() const return state; } -// Qt does not reference count accessibles -void BrowserAccessibilityQt::NativeAddReference() -{ -} - -// there is no reference counting, but BrowserAccessibility::Destroy -// calls this (and that is the only place in the chromium sources, -// so we can safely use it to dispose of ourselves here -// (the default implementation of this function just contains a "delete this") -void BrowserAccessibilityQt::NativeReleaseReference() +void BrowserAccessibilityQt::Destroy() { // delete this QAccessible::Id interfaceId = QAccessible::uniqueId(this); @@ -950,7 +977,7 @@ QAccessibleInterface *BrowserAccessibilityQt::table() const while (find_table && find_table->GetRole() != ax::mojom::Role::kTable) find_table = find_table->PlatformGetParent(); if (!find_table) - return 0; + return nullptr; return static_cast<BrowserAccessibilityQt*>(find_table); } @@ -961,4 +988,4 @@ void BrowserAccessibilityQt::modelChange(QAccessibleTableModelChangeEvent *) } // namespace content -#endif // QT_NO_ACCESSIBILITY +#endif // QT_CONFIG(accessibility) diff --git a/src/core/browser_accessibility_qt.h b/src/core/browser_accessibility_qt.h index decfc1e9d..32a4fc76b 100644 --- a/src/core/browser_accessibility_qt.h +++ b/src/core/browser_accessibility_qt.h @@ -43,7 +43,7 @@ #include <QtGui/qaccessible.h> #include "content/browser/accessibility/browser_accessibility.h" -#ifndef QT_NO_ACCESSIBILITY +#if QT_CONFIG(accessibility) namespace content { @@ -68,6 +68,7 @@ public: // navigation, hierarchy QAccessibleInterface *parent() const override; QAccessibleInterface *child(int index) const override; + QAccessibleInterface *focusChild() const override; int childCount() const override; int indexOfChild(const QAccessibleInterface *) const override; @@ -79,9 +80,7 @@ public: QAccessible::State state() const override; // BrowserAccessible - void NativeAddReference() override; - void NativeReleaseReference() override; - bool IsNative() const override { return true; } + void Destroy() override; // QAccessibleActionInterface QStringList actionNames() const override; @@ -150,5 +149,5 @@ QAccessibleInterface *toQAccessibleInterface(BrowserAccessibility *acc); } // namespace content -#endif // QT_NO_ACCESSIBILITY +#endif // QT_CONFIG(accessibility) #endif diff --git a/src/core/browser_main_parts_qt.cpp b/src/core/browser_main_parts_qt.cpp index 3e9af8167..bc0499bca 100644 --- a/src/core/browser_main_parts_qt.cpp +++ b/src/core/browser_main_parts_qt.cpp @@ -41,13 +41,17 @@ #include "api/qwebenginemessagepumpscheduler_p.h" -#include "base/message_loop/message_loop.h" -#include "base/message_loop/message_loop_current.h" #include "base/message_loop/message_pump_for_ui.h" #include "base/process/process.h" +#include "base/task/current_thread.h" #include "base/task/sequence_manager/sequence_manager_impl.h" #include "base/task/sequence_manager/thread_controller_with_message_pump_impl.h" #include "base/threading/thread_restrictions.h" +#include "chrome/browser/tab_contents/form_interaction_tab_helper.h" +#include "components/performance_manager/embedder/performance_manager_lifetime.h" +#include "components/performance_manager/embedder/performance_manager_registry.h" +#include "components/performance_manager/public/graph/graph.h" +#include "components/performance_manager/public/performance_manager.h" #include "content/public/browser/browser_main_parts.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/child_process_security_policy.h" @@ -55,18 +59,18 @@ #include "content/public/common/service_manager_connection.h" #include "extensions/buildflags/buildflags.h" #if BUILDFLAG(ENABLE_EXTENSIONS) +#include "content/public/browser/plugin_service.h" #include "extensions/common/constants.h" #include "extensions/common/extensions_client.h" #include "extensions/extensions_browser_client_qt.h" #include "extensions/extension_system_factory_qt.h" +#include "extensions/plugin_service_filter_qt.h" #include "common/extensions/extensions_client_qt.h" #endif //BUILDFLAG(ENABLE_EXTENSIONS) -#include "services/resource_coordinator/public/cpp/resource_coordinator_features.h" #include "services/service_manager/public/cpp/connector.h" #include "services/service_manager/public/cpp/service.h" #include "ui/display/screen.h" -#include "service/service_qt.h" #include "web_engine_context.h" #include <QtGui/qtgui-config.h> @@ -76,7 +80,7 @@ #include <QOpenGLContext> #endif -#if defined(OS_MACOSX) +#if defined(OS_MAC) #include "base/message_loop/message_pump_mac.h" #include "ui/base/idle/idle.h" #endif @@ -147,7 +151,7 @@ private: void ensureDelegate() { if (!m_delegate) { - auto seqMan = base::MessageLoopCurrent::GetCurrentSequenceManagerImpl(); + auto seqMan = base::CurrentThread::Get()->GetCurrentSequenceManagerImpl(); m_delegate = static_cast<base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl *>( seqMan->controller_.get()); } @@ -192,7 +196,7 @@ private: } private: - bool m_enabled = !QOpenGLContext::supportsThreadedOpenGL(); + bool m_enabled = WebEngineContext::isGpuServiceOnUIThread(); #endif // QT_CONFIG(opengl) }; @@ -201,19 +205,15 @@ private: { ScopedGLContextChecker glContextChecker; - bool more_work_is_plausible = m_delegate->DoWork(); + base::MessagePump::Delegate::NextWorkInfo more_work_info = m_delegate->DoWork(); - base::TimeTicks delayed_work_time; - more_work_is_plausible |= m_delegate->DoDelayedWork(&delayed_work_time); - - if (more_work_is_plausible) + if (more_work_info.is_immediate()) return ScheduleWork(); - more_work_is_plausible |= m_delegate->DoIdleWork(); - if (more_work_is_plausible) + if (m_delegate->DoIdleWork()) return ScheduleWork(); - ScheduleDelayedWork(delayed_work_time); + ScheduleDelayedWork(more_work_info.delayed_run_time); } Delegate *m_delegate = nullptr; @@ -227,7 +227,7 @@ std::unique_ptr<base::MessagePump> messagePumpFactory() madePrimaryPump = true; return std::make_unique<MessagePumpForUIQt>(); } -#if defined(OS_MACOSX) +#if defined(OS_MAC) return base::MessagePumpMac::Create(); #else return std::make_unique<base::MessagePumpForUI>(); @@ -252,11 +252,18 @@ void BrowserMainPartsQt::PreMainMessageLoopRun() extensions::ExtensionsClient::Set(new extensions::ExtensionsClientQt()); extensions::ExtensionsBrowserClient::Set(new extensions::ExtensionsBrowserClientQt()); extensions::ExtensionSystemFactoryQt::GetInstance(); + + content::PluginService *plugin_service = content::PluginService::GetInstance(); + plugin_service->SetFilter(extensions::PluginServiceFilterQt::GetInstance()); #endif //ENABLE_EXTENSIONS } void BrowserMainPartsQt::PostMainMessageLoopRun() { + performance_manager_registry_->TearDown(); + performance_manager_registry_.reset(); + performance_manager::DestroyPerformanceManager(std::move(performance_manager_)); + // The ProfileQt's destructor uses the MessageLoop so it should be deleted // right before the RenderProcessHostImpl's destructor destroys it. WebEngineContext::current()->destroyProfileAdapter(); @@ -266,7 +273,7 @@ int BrowserMainPartsQt::PreCreateThreads() { base::ThreadRestrictions::SetIOAllowed(true); -#if defined(OS_MACOSX) +#if defined(OS_MAC) ui::InitIdleMonitor(); #endif @@ -279,10 +286,17 @@ int BrowserMainPartsQt::PreCreateThreads() return 0; } +static void CreatePoliciesAndDecorators(performance_manager::Graph *graph) +{ + graph->PassToGraph(FormInteractionTabHelper::CreateGraphObserver()); +} + void BrowserMainPartsQt::PostCreateThreads() { - ServiceQt::GetInstance()->InitConnector(); - content::GetSystemConnector()->WarmService(service_manager::ServiceFilter::ByName("qtwebengine")); + performance_manager_ = + performance_manager::CreatePerformanceManagerWithDefaultDecorators( + base::BindOnce(&QtWebEngineCore::CreatePoliciesAndDecorators)); + performance_manager_registry_ = performance_manager::PerformanceManagerRegistry::Create(); } } // namespace QtWebEngineCore diff --git a/src/core/browser_main_parts_qt.h b/src/core/browser_main_parts_qt.h index f287c2e44..9d0967612 100644 --- a/src/core/browser_main_parts_qt.h +++ b/src/core/browser_main_parts_qt.h @@ -50,6 +50,11 @@ namespace content { class ServiceManagerConnection; } +namespace performance_manager { +class PerformanceManager; +class PerformanceManagerRegistry; +} + namespace QtWebEngineCore { std::unique_ptr<base::MessagePump> messagePumpFactory(); @@ -69,6 +74,8 @@ public: private: DISALLOW_COPY_AND_ASSIGN(BrowserMainPartsQt); + std::unique_ptr<performance_manager::PerformanceManager> performance_manager_; + std::unique_ptr<performance_manager::PerformanceManagerRegistry> performance_manager_registry_; }; } // namespace QtWebEngineCore diff --git a/src/core/browser_message_filter_qt.cpp b/src/core/browser_message_filter_qt.cpp index a4b75f075..54d6551e4 100644 --- a/src/core/browser_message_filter_qt.cpp +++ b/src/core/browser_message_filter_qt.cpp @@ -64,90 +64,77 @@ BrowserMessageFilterQt::BrowserMessageFilterQt(int /*render_process_id*/, Profil bool BrowserMessageFilterQt::OnMessageReceived(const IPC::Message& message) { IPC_BEGIN_MESSAGE_MAP(BrowserMessageFilterQt, message) - IPC_MESSAGE_HANDLER(QtWebEngineHostMsg_AllowDatabase, OnAllowDatabase) - IPC_MESSAGE_HANDLER(QtWebEngineHostMsg_AllowDOMStorage, OnAllowDOMStorage) - IPC_MESSAGE_HANDLER_DELAY_REPLY(QtWebEngineHostMsg_RequestFileSystemAccessSync, - OnRequestFileSystemAccessSync) - IPC_MESSAGE_HANDLER(QtWebEngineHostMsg_RequestFileSystemAccessAsync, - OnRequestFileSystemAccessAsync) - IPC_MESSAGE_HANDLER(QtWebEngineHostMsg_AllowIndexedDB, OnAllowIndexedDB) + IPC_MESSAGE_HANDLER(QtWebEngineHostMsg_AllowStorageAccess, OnAllowStorageAccess) + IPC_MESSAGE_HANDLER_DELAY_REPLY(QtWebEngineHostMsg_RequestStorageAccessSync, + OnRequestStorageAccessSync) + IPC_MESSAGE_HANDLER(QtWebEngineHostMsg_RequestStorageAccessAsync, + OnRequestStorageAccessAsync) IPC_MESSAGE_UNHANDLED(return false) IPC_END_MESSAGE_MAP() return true; } -void BrowserMessageFilterQt::OnAllowDatabase(int /*render_frame_id*/, - const GURL &origin_url, - const GURL &top_origin_url, - bool* allowed) +void BrowserMessageFilterQt::OnAllowStorageAccess(int /*render_frame_id*/, + const GURL &origin_url, + const GURL &top_origin_url, + int /*storage_type*/, + bool *allowed) { *allowed = m_profileData->canGetCookies(toQt(top_origin_url), toQt(origin_url)); } -void BrowserMessageFilterQt::OnAllowDOMStorage(int /*render_frame_id*/, - const GURL &origin_url, - const GURL &top_origin_url, - bool /*local*/, - bool *allowed) -{ - *allowed = m_profileData->canGetCookies(toQt(top_origin_url), toQt(origin_url)); -} - -void BrowserMessageFilterQt::OnAllowIndexedDB(int /*render_frame_id*/, - const GURL &origin_url, - const GURL &top_origin_url, - bool *allowed) -{ - *allowed = m_profileData->canGetCookies(toQt(top_origin_url), toQt(origin_url)); -} - -void BrowserMessageFilterQt::OnRequestFileSystemAccessSync(int render_frame_id, - const GURL& origin_url, - const GURL& top_origin_url, - IPC::Message* reply_msg) +void BrowserMessageFilterQt::OnRequestStorageAccessSync(int render_frame_id, + const GURL& origin_url, + const GURL& top_origin_url, + int storage_type, + IPC::Message* reply_msg) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); base::Callback<void(bool)> callback = base::Bind( - &BrowserMessageFilterQt::OnRequestFileSystemAccessSyncResponse, + &BrowserMessageFilterQt::OnRequestStorageAccessSyncResponse, base::WrapRefCounted(this), reply_msg); - OnRequestFileSystemAccess(render_frame_id, - origin_url, - top_origin_url, - callback); + OnRequestStorageAccess(render_frame_id, + origin_url, + top_origin_url, + storage_type, + callback); } -void BrowserMessageFilterQt::OnRequestFileSystemAccessSyncResponse(IPC::Message *reply_msg, bool allowed) +void BrowserMessageFilterQt::OnRequestStorageAccessSyncResponse(IPC::Message *reply_msg, bool allowed) { - QtWebEngineHostMsg_RequestFileSystemAccessSync::WriteReplyParams(reply_msg, allowed); + QtWebEngineHostMsg_RequestStorageAccessSync::WriteReplyParams(reply_msg, allowed); Send(reply_msg); } -void BrowserMessageFilterQt::OnRequestFileSystemAccessAsync(int render_frame_id, - int request_id, - const GURL& origin_url, - const GURL& top_origin_url) +void BrowserMessageFilterQt::OnRequestStorageAccessAsync(int render_frame_id, + int request_id, + const GURL& origin_url, + const GURL& top_origin_url, + int storage_type) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); base::Callback<void(bool)> callback = base::Bind( - &BrowserMessageFilterQt::OnRequestFileSystemAccessAsyncResponse, + &BrowserMessageFilterQt::OnRequestStorageAccessAsyncResponse, base::WrapRefCounted(this), render_frame_id, request_id); - OnRequestFileSystemAccess(render_frame_id, - origin_url, - top_origin_url, - callback); + OnRequestStorageAccess(render_frame_id, + origin_url, + top_origin_url, + storage_type, + callback); } -void BrowserMessageFilterQt::OnRequestFileSystemAccessAsyncResponse(int render_frame_id, - int request_id, - bool allowed) +void BrowserMessageFilterQt::OnRequestStorageAccessAsyncResponse(int render_frame_id, + int request_id, + bool allowed) { - Send(new QtWebEngineMsg_RequestFileSystemAccessAsyncResponse(render_frame_id, request_id, allowed)); + Send(new QtWebEngineMsg_RequestStorageAccessAsyncResponse(render_frame_id, request_id, allowed)); } -void BrowserMessageFilterQt::OnRequestFileSystemAccess(int /*render_frame_id*/, - const GURL &origin_url, - const GURL &top_origin_url, - base::Callback<void(bool)> callback) +void BrowserMessageFilterQt::OnRequestStorageAccess(int /*render_frame_id*/, + const GURL &origin_url, + const GURL &top_origin_url, + int /*storage_type*/, + base::Callback<void(bool)> callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); bool allowed = m_profileData->canGetCookies(toQt(top_origin_url), toQt(origin_url)); diff --git a/src/core/browser_message_filter_qt.h b/src/core/browser_message_filter_qt.h index 4abc612f8..85de0486a 100644 --- a/src/core/browser_message_filter_qt.h +++ b/src/core/browser_message_filter_qt.h @@ -42,7 +42,6 @@ #include "base/callback.h" #include "content/public/browser/browser_message_filter.h" -#include "content/public/common/webplugininfo.h" class GURL; class Profile; @@ -59,39 +58,33 @@ public: private: bool OnMessageReceived(const IPC::Message& message) override; - void OnAllowDatabase(int render_frame_id, - const GURL &origin_url, - const GURL &top_origin_url, - bool *allowed); - void OnAllowDOMStorage(int render_frame_id, - const GURL &origin_url, - const GURL &top_origin_url, - bool local, - bool *allowed); + void OnAllowStorageAccess(int render_frame_id, + const GURL &origin_url, + const GURL &top_origin_url, + int storage_type, + bool *allowed); - void OnAllowIndexedDB(int render_frame_id, - const GURL &origin_url, - const GURL &top_origin_url, - bool *allowed); - - void OnRequestFileSystemAccessSync(int render_frame_id, - const GURL &origin_url, - const GURL &top_origin_url, - IPC::Message *message); - void OnRequestFileSystemAccessAsync(int render_frame_id, - int request_id, - const GURL &origin_url, - const GURL &top_origin_url); - void OnRequestFileSystemAccessSyncResponse(IPC::Message *reply_msg, - bool allowed); - void OnRequestFileSystemAccessAsyncResponse(int render_frame_id, - int request_id, - bool allowed); - void OnRequestFileSystemAccess(int render_frame_id, - const GURL &origin_url, - const GURL &top_origin_url, - base::Callback<void(bool)> callback); + void OnRequestStorageAccessSync(int render_frame_id, + const GURL &origin_url, + const GURL &top_origin_url, + int storage_type, + IPC::Message *message); + void OnRequestStorageAccessAsync(int render_frame_id, + int request_id, + const GURL &origin_url, + const GURL &top_origin_url, + int storage_type); + void OnRequestStorageAccessSyncResponse(IPC::Message *reply_msg, + bool allowed); + void OnRequestStorageAccessAsyncResponse(int render_frame_id, + int request_id, + bool allowed); + void OnRequestStorageAccess(int render_frame_id, + const GURL &origin_url, + const GURL &top_origin_url, + int storage_type, + base::Callback<void(bool)> callback); ProfileIODataQt *m_profileData; }; diff --git a/src/core/browsing_data_remover_delegate_qt.cpp b/src/core/browsing_data_remover_delegate_qt.cpp index 344ba817f..6e79ab6c6 100644 --- a/src/core/browsing_data_remover_delegate_qt.cpp +++ b/src/core/browsing_data_remover_delegate_qt.cpp @@ -48,7 +48,7 @@ namespace QtWebEngineCore { -bool DoesOriginMatchEmbedderMask(int origin_type_mask, +bool DoesOriginMatchEmbedderMask(uint64_t origin_type_mask, const url::Origin &origin, storage::SpecialStoragePolicy *policy) { @@ -70,10 +70,10 @@ bool BrowsingDataRemoverDelegateQt::MayRemoveDownloadHistory() void BrowsingDataRemoverDelegateQt::RemoveEmbedderData(const base::Time &delete_begin, const base::Time &delete_end, - int remove_mask, + uint64_t remove_mask, content::BrowsingDataFilterBuilder *filter_builder, - int origin_type_mask, - base::OnceClosure callback) + uint64_t origin_type_mask, + base::OnceCallback<void(/*failed_data_types=*/uint64_t)> callback) { Q_UNUSED(delete_begin); Q_UNUSED(delete_end); @@ -83,7 +83,12 @@ void BrowsingDataRemoverDelegateQt::RemoveEmbedderData(const base::Time &delete_ if (remove_mask & content::BrowsingDataRemover::DATA_TYPE_CACHE) web_cache::WebCacheManager::GetInstance()->ClearCache(); - std::move(callback).Run(); + std::move(callback).Run(0); +} + +std::vector<std::string> BrowsingDataRemoverDelegateQt::GetDomainsForDeferredCookieDeletion(uint64_t) +{ + return {}; } } // namespace QtWebEngineCore diff --git a/src/core/browsing_data_remover_delegate_qt.h b/src/core/browsing_data_remover_delegate_qt.h index dc2761ffc..5adfbbe7e 100644 --- a/src/core/browsing_data_remover_delegate_qt.h +++ b/src/core/browsing_data_remover_delegate_qt.h @@ -40,6 +40,8 @@ #ifndef BROWSING_DATA_REMOVER_DELEGATE_QT_H #define BROWSING_DATA_REMOVER_DELEGATE_QT_H +#include <cstdint> + #include "content/public/browser/browsing_data_remover_delegate.h" namespace QtWebEngineCore { @@ -55,10 +57,11 @@ public: void RemoveEmbedderData( const base::Time &delete_begin, const base::Time &delete_end, - int remove_mask, + uint64_t remove_mask, content::BrowsingDataFilterBuilder *filter_builder, - int origin_type_mask, - base::OnceClosure callback) override; + uint64_t origin_type_mask, + base::OnceCallback<void(/*failed_data_types=*/uint64_t)> callback) override; + std::vector<std::string> GetDomainsForDeferredCookieDeletion(uint64_t) override; }; } // namespace QtWebEngineCore diff --git a/src/core/certificate_error_controller.cpp b/src/core/certificate_error_controller.cpp index f3b16357b..d9043bf8e 100644 --- a/src/core/certificate_error_controller.cpp +++ b/src/core/certificate_error_controller.cpp @@ -53,7 +53,6 @@ QT_BEGIN_NAMESPACE using namespace QtWebEngineCore; ASSERT_ENUMS_MATCH(CertificateErrorController::SslPinnedKeyNotInCertificateChain, net::ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN) -ASSERT_ENUMS_MATCH(CertificateErrorController::CertificateCommonNameInvalid, net::ERR_CERT_BEGIN) ASSERT_ENUMS_MATCH(CertificateErrorController::CertificateCommonNameInvalid, net::ERR_CERT_COMMON_NAME_INVALID) ASSERT_ENUMS_MATCH(CertificateErrorController::CertificateDateInvalid, net::ERR_CERT_DATE_INVALID) ASSERT_ENUMS_MATCH(CertificateErrorController::CertificateAuthorityInvalid, net::ERR_CERT_AUTHORITY_INVALID) @@ -68,11 +67,13 @@ ASSERT_ENUMS_MATCH(CertificateErrorController::CertificateNameConstraintViolatio ASSERT_ENUMS_MATCH(CertificateErrorController::CertificateValidityTooLong, net::ERR_CERT_VALIDITY_TOO_LONG) ASSERT_ENUMS_MATCH(CertificateErrorController::CertificateTransparencyRequired, net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED) ASSERT_ENUMS_MATCH(CertificateErrorController::CertificateSymantecLegacy, net::ERR_CERT_SYMANTEC_LEGACY) +ASSERT_ENUMS_MATCH(CertificateErrorController::CertificateKnownInterceptionBlocked, net::ERR_CERT_KNOWN_INTERCEPTION_BLOCKED) +ASSERT_ENUMS_MATCH(CertificateErrorController::SslObsoleteVersion, net::ERR_SSL_OBSOLETE_VERSION) ASSERT_ENUMS_MATCH(CertificateErrorController::CertificateErrorEnd, net::ERR_CERT_END) void CertificateErrorControllerPrivate::accept(bool accepted) { - callback.Run(accepted ? content::CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE : content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY); + std::move(callback).Run(accepted ? content::CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE : content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY); } CertificateErrorControllerPrivate::CertificateErrorControllerPrivate(int cert_error, @@ -81,14 +82,14 @@ CertificateErrorControllerPrivate::CertificateErrorControllerPrivate(int cert_er bool main_frame, bool fatal_error, bool strict_enforcement, - const base::Callback<void(content::CertificateRequestResultType)>& cb + base::OnceCallback<void(content::CertificateRequestResultType)> cb ) : certError(CertificateErrorController::CertificateError(cert_error)) , requestUrl(toQt(request_url)) , resourceType(main_frame ? CertificateErrorController::ResourceTypeMainFrame : CertificateErrorController::ResourceTypeOther) , fatalError(fatal_error) , strictEnforcement(strict_enforcement) - , callback(cb) + , callback(std::move(cb)) { if (auto cert = ssl_info.cert.get()) { validStart = toQt(cert->valid_start()); @@ -158,11 +159,13 @@ QString CertificateErrorController::errorString() const else return getQStringForMessageId(IDS_CERT_ERROR_NOT_YET_VALID_DESCRIPTION); case CertificateAuthorityInvalid: + case CertificateKnownInterceptionBlocked: + case CertificateSymantecLegacy: return getQStringForMessageId(IDS_CERT_ERROR_AUTHORITY_INVALID_DESCRIPTION); case CertificateContainsErrors: return getQStringForMessageId(IDS_CERT_ERROR_CONTAINS_ERRORS_DESCRIPTION); case CertificateNoRevocationMechanism: - return getQStringForMessageId(IDS_CERT_ERROR_NO_REVOCATION_MECHANISM_DETAILS); + return getQStringForMessageId(IDS_CERT_ERROR_NO_REVOCATION_MECHANISM_DESCRIPTION); case CertificateRevoked: return getQStringForMessageId(IDS_CERT_ERROR_REVOKED_CERT_DESCRIPTION); case CertificateInvalid: @@ -179,6 +182,8 @@ QString CertificateErrorController::errorString() const return getQStringForMessageId(IDS_CERT_ERROR_VALIDITY_TOO_LONG_DESCRIPTION); case CertificateTransparencyRequired: return getQStringForMessageId(IDS_CERT_ERROR_CERTIFICATE_TRANSPARENCY_REQUIRED_DESCRIPTION); + case SslObsoleteVersion: + return getQStringForMessageId(IDS_SSL_ERROR_OBSOLETE_VERSION_DESCRIPTION); case CertificateUnableToCheckRevocation: // Deprecated in Chromium. default: break; diff --git a/src/core/certificate_error_controller.h b/src/core/certificate_error_controller.h index d7e057adf..740f7a9d4 100644 --- a/src/core/certificate_error_controller.h +++ b/src/core/certificate_error_controller.h @@ -85,8 +85,9 @@ public: CertificateValidityTooLong = -213, CertificateTransparencyRequired = -214, CertificateSymantecLegacy = -215, - - CertificateErrorEnd = -216 // not an error, just an enum boundary + CertificateKnownInterceptionBlocked = -217, + SslObsoleteVersion = -218, + CertificateErrorEnd = -219 // not an error, just an enum boundary }; CertificateError error() const; diff --git a/src/core/certificate_error_controller_p.h b/src/core/certificate_error_controller_p.h index ceae99853..b0b0bc658 100644 --- a/src/core/certificate_error_controller_p.h +++ b/src/core/certificate_error_controller_p.h @@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE class CertificateErrorControllerPrivate { public: - CertificateErrorControllerPrivate(int cert_error, const net::SSLInfo& ssl_info, const GURL& request_url, bool main_frame, bool fatal_error, bool strict_enforcement, const base::Callback<void(content::CertificateRequestResultType)>& callback); + CertificateErrorControllerPrivate(int cert_error, const net::SSLInfo& ssl_info, const GURL& request_url, bool main_frame, bool fatal_error, bool strict_enforcement, base::OnceCallback<void(content::CertificateRequestResultType)> callback); void accept(bool accepted); @@ -70,7 +70,7 @@ public: CertificateErrorController::ResourceType resourceType; bool fatalError; bool strictEnforcement; - const base::Callback<void(content::CertificateRequestResultType)> callback; + base::OnceCallback<void(content::CertificateRequestResultType)> callback; QList<QSslCertificate> certificateChain; }; diff --git a/src/core/chromium_overrides.cpp b/src/core/chromium_overrides.cpp index 9d3e3f08a..8a385e4a8 100644 --- a/src/core/chromium_overrides.cpp +++ b/src/core/chromium_overrides.cpp @@ -43,7 +43,6 @@ #include "base/values.h" #include "content/browser/accessibility/accessibility_tree_formatter_blink.h" -#include "content/browser/accessibility/accessibility_tree_formatter_browser.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/common/font_list.h" @@ -51,7 +50,6 @@ #include "ui/base/dragdrop/os_exchange_data_provider_factory.h" #include "ui/events/devices/device_data_manager.h" #include "ui/events/platform/platform_event_source.h" -#include "ui/snapshot/snapshot.h" #include "ppapi/buildflags/buildflags.h" #include <QGuiApplication> @@ -63,7 +61,6 @@ #if defined(USE_AURA) && !defined(USE_OZONE) #include "ui/base/dragdrop/os_exchange_data.h" -#include "ui/base/dragdrop/os_exchange_data_provider_aura.h" #include "ui/gfx/render_text.h" #include "ui/gfx/platform_font.h" #endif @@ -72,6 +69,10 @@ #include "net/ssl/openssl_client_key_store.h" #endif +#if !QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) +#include "chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h" +#endif + void *GetQtXDisplay() { return GLContextHelper::getXDisplay(); @@ -148,54 +149,81 @@ std::vector<AccessibilityTreeFormatter::TestPass> AccessibilityTreeFormatter::Ge } } // namespace content -#if defined(USE_AURA) -namespace ui { +std::unique_ptr<ui::OSExchangeDataProvider> ui::OSExchangeDataProviderFactory::CreateProvider() +{ + return nullptr; +} -bool GrabWindowSnapshot(gfx::NativeWindow window, - const gfx::Rect& snapshot_bounds, - gfx::Image* image) +#if !QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) +namespace extensions { +ExtensionFunction::ResponseAction WebrtcLoggingPrivateSetMetaDataFunction::Run() { - NOTIMPLEMENTED(); - return false; + return RespondNow(NoArguments()); } -bool GrabViewSnapshot(gfx::NativeView view, - const gfx::Rect& snapshot_bounds, - gfx::Image* image) +ExtensionFunction::ResponseAction WebrtcLoggingPrivateStartFunction::Run() { - NOTIMPLEMENTED(); - return false; + return RespondNow(NoArguments()); } -void GrabWindowSnapshotAndScaleAsync(gfx::NativeWindow window, - const gfx::Rect& source_rect, - const gfx::Size& target_size, - const GrabWindowSnapshotAsyncCallback& callback) +ExtensionFunction::ResponseAction WebrtcLoggingPrivateSetUploadOnRenderCloseFunction::Run() { - NOTIMPLEMENTED(); - callback.Run(gfx::Image()); + return RespondNow(NoArguments()); } -void GrabWindowSnapshotAsync(gfx::NativeWindow window, - const gfx::Rect& source_rect, - const GrabWindowSnapshotAsyncCallback& callback) +ExtensionFunction::ResponseAction WebrtcLoggingPrivateStopFunction::Run() { - NOTIMPLEMENTED(); - callback.Run(gfx::Image()); + return RespondNow(NoArguments()); } -void GrabViewSnapshotAsync(gfx::NativeView view, - const gfx::Rect& source_rect, - const GrabWindowSnapshotAsyncCallback& callback) +ExtensionFunction::ResponseAction WebrtcLoggingPrivateStoreFunction::Run() { - NOTIMPLEMENTED(); - callback.Run(gfx::Image()); + return RespondNow(NoArguments()); } -} // namespace ui -#endif // defined(USE_AURA) +ExtensionFunction::ResponseAction WebrtcLoggingPrivateUploadStoredFunction::Run() +{ + return RespondNow(NoArguments()); +} -std::unique_ptr<ui::OSExchangeData::Provider> -ui::OSExchangeDataProviderFactory::CreateProvider() { - return nullptr; +ExtensionFunction::ResponseAction WebrtcLoggingPrivateUploadFunction::Run() +{ + return RespondNow(NoArguments()); +} + +ExtensionFunction::ResponseAction WebrtcLoggingPrivateDiscardFunction::Run() +{ + return RespondNow(NoArguments()); +} + +ExtensionFunction::ResponseAction WebrtcLoggingPrivateStartRtpDumpFunction::Run() +{ + return RespondNow(NoArguments()); +} + +ExtensionFunction::ResponseAction WebrtcLoggingPrivateStopRtpDumpFunction::Run() +{ + return RespondNow(NoArguments()); +} + +ExtensionFunction::ResponseAction WebrtcLoggingPrivateStartAudioDebugRecordingsFunction::Run() +{ + return RespondNow(NoArguments()); +} + +ExtensionFunction::ResponseAction WebrtcLoggingPrivateStopAudioDebugRecordingsFunction::Run() +{ + return RespondNow(NoArguments()); +} + +ExtensionFunction::ResponseAction WebrtcLoggingPrivateStartEventLoggingFunction::Run() +{ + return RespondNow(NoArguments()); +} + +ExtensionFunction::ResponseAction WebrtcLoggingPrivateGetLogsDirectoryFunction::Run() +{ + return RespondNow(NoArguments()); } +} // namespace extensions +#endif // !QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) diff --git a/src/core/clipboard_qt.cpp b/src/core/clipboard_qt.cpp index 70e0a2376..65e3e90ac 100644 --- a/src/core/clipboard_qt.cpp +++ b/src/core/clipboard_qt.cpp @@ -46,10 +46,12 @@ #include "type_conversion.h" #include "base/logging.h" +#include "base/strings/utf_string_conversions.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/clipboard/custom_data_helper.h" #include "ui/base/clipboard/clipboard.h" #include "ui/base/clipboard/clipboard_constants.h" +#include "ui/base/clipboard/clipboard_data_endpoint.h" #include "ui/base/clipboard/clipboard_format_type.h" #include <QGuiApplication> @@ -105,30 +107,40 @@ Clipboard *Clipboard::Create() namespace QtWebEngineCore { -void ClipboardQt::WriteObjects(ui::ClipboardType type, const ObjectMap &objects) +void ClipboardQt::WritePortableRepresentations(ui::ClipboardBuffer type, const ObjectMap &objects, std::unique_ptr<ui::ClipboardDataEndpoint> data_src) { DCHECK(CalledOnValidThread()); - DCHECK(IsSupportedClipboardType(type)); + DCHECK(IsSupportedClipboardBuffer(type)); - for (ObjectMap::const_iterator iter = objects.begin(); iter != objects.end(); ++iter) - DispatchObject(static_cast<ObjectType>(iter->first), iter->second); + for (const auto &object : objects) + DispatchPortableRepresentation(object.first, object.second); // Commit the accumulated data. if (uncommittedData) QGuiApplication::clipboard()->setMimeData(uncommittedData.take(), - type == ui::ClipboardType::kCopyPaste ? QClipboard::Clipboard - : QClipboard::Selection); + type == ui::ClipboardBuffer::kCopyPaste ? QClipboard::Clipboard + : QClipboard::Selection); - if (type == ui::ClipboardType::kCopyPaste && IsSupportedClipboardType(ui::ClipboardType::kSelection)) { - ObjectMap::const_iterator text_iter = objects.find(CBF_TEXT); + if (type == ui::ClipboardBuffer::kCopyPaste && IsSupportedClipboardBuffer(ui::ClipboardBuffer::kSelection)) { + ObjectMap::const_iterator text_iter = objects.find(PortableFormat::kText); if (text_iter != objects.end()) { // Copy text and SourceTag to the selection clipboard. - ObjectMap::const_iterator next_iter = text_iter; - WriteObjects(ui::ClipboardType::kSelection, ObjectMap(text_iter, ++next_iter, base::KEEP_FIRST_OF_DUPES)); + WritePortableRepresentations(ui::ClipboardBuffer::kSelection, + ObjectMap(text_iter, text_iter + 1), + std::move(data_src)); } } } +void ClipboardQt::WritePlatformRepresentations(ui::ClipboardBuffer buffer, + std::vector<ui::Clipboard::PlatformRepresentation> platform_representations, + std::unique_ptr<ui::ClipboardDataEndpoint> data_src) +{ + DCHECK(CalledOnValidThread()); + DCHECK(IsSupportedClipboardBuffer(buffer)); + DispatchPlatformRepresentations(std::move(platform_representations)); +} + void ClipboardQt::WriteText(const char *text_data, size_t text_len) { getUncommittedData()->setText(QString::fromUtf8(text_data, text_len)); @@ -136,7 +148,14 @@ void ClipboardQt::WriteText(const char *text_data, size_t text_len) void ClipboardQt::WriteHTML(const char *markup_data, size_t markup_len, const char *url_data, size_t url_len) { - getUncommittedData()->setHtml(QString::fromUtf8(markup_data, markup_len)); + QString markup_string = QString::fromUtf8(markup_data, markup_len); +#if defined (Q_OS_MACOS) + // We need to prepend the charset on macOS to prevent garbled Unicode characters + // when pasting to certain applications (e.g. Notes, TextEdit) + // Mirrors the behavior in ui/base/clipboard/clipboard_mac.mm in Chromium. + markup_string.prepend(QLatin1String("<meta charset='utf-8'>")); +#endif + getUncommittedData()->setHtml(markup_string); } void ClipboardQt::WriteRTF(const char *rtf_data, size_t data_len) @@ -170,33 +189,36 @@ void ClipboardQt::WriteBookmark(const char *title_data, size_t title_len, const void ClipboardQt::WriteData(const ui::ClipboardFormatType &format, const char *data_data, size_t data_len) { - getUncommittedData()->setData(QString::fromStdString(format.ToString()), QByteArray(data_data, data_len)); + getUncommittedData()->setData(QString::fromStdString(format.GetName()), QByteArray(data_data, data_len)); } -bool ClipboardQt::IsFormatAvailable(const ui::ClipboardFormatType &format, ui::ClipboardType type) const +bool ClipboardQt::IsFormatAvailable(const ui::ClipboardFormatType &format, + ui::ClipboardBuffer type, + const ui::ClipboardDataEndpoint *data_dst) const { const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData( - type == ui::ClipboardType::kCopyPaste ? QClipboard::Clipboard : QClipboard::Selection); - return mimeData && mimeData->hasFormat(QString::fromStdString(format.ToString())); + type == ui::ClipboardBuffer::kCopyPaste ? QClipboard::Clipboard : QClipboard::Selection); + return mimeData && mimeData->hasFormat(QString::fromStdString(format.GetName())); } -void ClipboardQt::Clear(ui::ClipboardType type) +void ClipboardQt::Clear(ui::ClipboardBuffer type) { - QGuiApplication::clipboard()->clear(type == ui::ClipboardType::kCopyPaste ? QClipboard::Clipboard + QGuiApplication::clipboard()->clear(type == ui::ClipboardBuffer::kCopyPaste ? QClipboard::Clipboard : QClipboard::Selection); } -void ClipboardQt::ReadAvailableTypes(ui::ClipboardType type, std::vector<base::string16> *types, - bool *contains_filenames) const +void ClipboardQt::ReadAvailableTypes(ui::ClipboardBuffer type, + const ui::ClipboardDataEndpoint *data_dst, + std::vector<base::string16> *types) const { - if (!types || !contains_filenames) { + if (!types) { NOTREACHED(); return; } types->clear(); const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData( - type == ui::ClipboardType::kCopyPaste ? QClipboard::Clipboard : QClipboard::Selection); + type == ui::ClipboardBuffer::kCopyPaste ? QClipboard::Clipboard : QClipboard::Selection); if (!mimeData) return; if (mimeData->hasImage() && !mimeData->formats().contains(QStringLiteral("image/png"))) @@ -204,29 +226,34 @@ void ClipboardQt::ReadAvailableTypes(ui::ClipboardType type, std::vector<base::s const QStringList formats = mimeData->formats(); for (const QString &mimeType : formats) types->push_back(toString16(mimeType)); - *contains_filenames = false; const QByteArray customData = mimeData->data(QString::fromLatin1(ui::kMimeTypeWebCustomData)); ui::ReadCustomDataTypes(customData.constData(), customData.size(), types); } -void ClipboardQt::ReadText(ui::ClipboardType type, base::string16 *result) const +void ClipboardQt::ReadText(ui::ClipboardBuffer type, + const ui::ClipboardDataEndpoint *data_dst, + base::string16 *result) const { const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData( - type == ui::ClipboardType::kCopyPaste ? QClipboard::Clipboard : QClipboard::Selection); + type == ui::ClipboardBuffer::kCopyPaste ? QClipboard::Clipboard : QClipboard::Selection); if (mimeData) *result = toString16(mimeData->text()); } -void ClipboardQt::ReadAsciiText(ui::ClipboardType type, std::string *result) const +void ClipboardQt::ReadAsciiText(ui::ClipboardBuffer type, + const ui::ClipboardDataEndpoint *data_dst, + std::string *result) const { const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData( - type == ui::ClipboardType::kCopyPaste ? QClipboard::Clipboard : QClipboard::Selection); + type == ui::ClipboardBuffer::kCopyPaste ? QClipboard::Clipboard : QClipboard::Selection); if (mimeData) *result = mimeData->text().toStdString(); } -void ClipboardQt::ReadHTML(ui::ClipboardType type, base::string16 *markup, std::string *src_url, +void ClipboardQt::ReadHTML(ui::ClipboardBuffer type, + const ui::ClipboardDataEndpoint *data_dst, + base::string16 *markup, std::string *src_url, uint32_t *fragment_start, uint32_t *fragment_end) const { markup->clear(); @@ -236,29 +263,33 @@ void ClipboardQt::ReadHTML(ui::ClipboardType type, base::string16 *markup, std:: *fragment_end = 0; const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData( - type == ui::ClipboardType::kCopyPaste ? QClipboard::Clipboard : QClipboard::Selection); + type == ui::ClipboardBuffer::kCopyPaste ? QClipboard::Clipboard : QClipboard::Selection); if (!mimeData) return; *markup = toString16(mimeData->html()); *fragment_end = static_cast<uint32_t>(markup->length()); } -void ClipboardQt::ReadRTF(ui::ClipboardType type, std::string *result) const +void ClipboardQt::ReadRTF(ui::ClipboardBuffer type, + const ui::ClipboardDataEndpoint *data_dst, + std::string *result) const { const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData( - type == ui::ClipboardType::kCopyPaste ? QClipboard::Clipboard : QClipboard::Selection); + type == ui::ClipboardBuffer::kCopyPaste ? QClipboard::Clipboard : QClipboard::Selection); if (!mimeData) return; const QByteArray byteArray = mimeData->data(QString::fromLatin1(ui::kMimeTypeRTF)); *result = std::string(byteArray.constData(), byteArray.length()); } -SkBitmap ClipboardQt::ReadImage(ui::ClipboardType type) const +void ClipboardQt::ReadImage(ui::ClipboardBuffer type, + const ui::ClipboardDataEndpoint *data_dst, + ReadImageCallback callback) const { const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData( - type == ui::ClipboardType::kCopyPaste ? QClipboard::Clipboard : QClipboard::Selection); + type == ui::ClipboardBuffer::kCopyPaste ? QClipboard::Clipboard : QClipboard::Selection); if (!mimeData) - return SkBitmap(); + return std::move(callback).Run(SkBitmap()); QImage image = qvariant_cast<QImage>(mimeData->imageData()); image = image.convertToFormat(QImage::Format_ARGB32); @@ -276,37 +307,86 @@ SkBitmap ClipboardQt::ReadImage(ui::ClipboardType type) const src += bytesPerLineSrc; } - return bitmap; + return std::move(callback).Run(bitmap); } -void ClipboardQt::ReadCustomData(ui::ClipboardType clipboard_type, const base::string16 &type, base::string16 *result) const +void ClipboardQt::ReadCustomData(ui::ClipboardBuffer clipboard_type, const base::string16 &type, + const ui::ClipboardDataEndpoint *data_dst, + base::string16 *result) const { const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData( - clipboard_type == ui::ClipboardType::kCopyPaste ? QClipboard::Clipboard : QClipboard::Selection); + clipboard_type == ui::ClipboardBuffer::kCopyPaste ? QClipboard::Clipboard : QClipboard::Selection); if (!mimeData) return; const QByteArray customData = mimeData->data(QString::fromLatin1(ui::kMimeTypeWebCustomData)); ui::ReadCustomDataForType(customData.constData(), customData.size(), type, result); } -void ClipboardQt::ReadBookmark(base::string16 *title, std::string *url) const +void ClipboardQt::ReadBookmark(const ui::ClipboardDataEndpoint *data_dst, base::string16 *title, std::string *url) const { NOTIMPLEMENTED(); } -void ClipboardQt::ReadData(const ui::ClipboardFormatType &format, std::string *result) const +void ClipboardQt::ReadSvg(ui::ClipboardBuffer clipboard_type, + const ui::ClipboardDataEndpoint *, + base::string16 *result) const +{ + const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData( + clipboard_type == ui::ClipboardBuffer::kCopyPaste ? QClipboard::Clipboard : QClipboard::Selection); + if (!mimeData) + return; + const QByteArray svgData = mimeData->data(QString::fromLatin1(ui::kMimeTypeSvg)); + if (!svgData.isEmpty()) + *result = toString16(QString::fromUtf8(svgData)); +} + +void ClipboardQt::WriteSvg(const char *svg_data, size_t data_len) +{ + getUncommittedData()->setData(QString::fromLatin1(ui::kMimeTypeSvg), + QByteArray(svg_data, data_len)); +} + +void ClipboardQt::ReadData(const ui::ClipboardFormatType &format, + const ui::ClipboardDataEndpoint *data_dst, + std::string *result) const { const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData(); if (!mimeData) return; - const QByteArray byteArray = mimeData->data(QString::fromStdString(format.ToString())); + const QByteArray byteArray = mimeData->data(QString::fromStdString(format.GetName())); *result = std::string(byteArray.constData(), byteArray.length()); } -uint64_t ClipboardQt::GetSequenceNumber(ui::ClipboardType type) const +uint64_t ClipboardQt::GetSequenceNumber(ui::ClipboardBuffer type) const +{ + return clipboardChangeObserver()->getSequenceNumber(type == ui::ClipboardBuffer::kCopyPaste ? QClipboard::Clipboard + : QClipboard::Selection); +} + + +#if defined(USE_OZONE) +bool ClipboardQt::IsSelectionBufferAvailable() const +{ + return QGuiApplication::clipboard()->supportsSelection(); +} +#endif + +std::vector<base::string16> ClipboardQt::ReadAvailablePlatformSpecificFormatNames(ui::ClipboardBuffer buffer, const ui::ClipboardDataEndpoint *data_dst) const { - return clipboardChangeObserver()->getSequenceNumber(type == ui::ClipboardType::kCopyPaste ? QClipboard::Clipboard - : QClipboard::Selection); + // based on ClipboardAura + std::vector<base::string16> types; + if (IsFormatAvailable(ui::ClipboardFormatType::GetPlainTextType(), buffer, data_dst)) + types.push_back(base::UTF8ToUTF16(ui::ClipboardFormatType::GetPlainTextType().GetName())); + if (IsFormatAvailable(ui::ClipboardFormatType::GetHtmlType(), buffer, data_dst)) + types.push_back(base::UTF8ToUTF16(ui::ClipboardFormatType::GetHtmlType().GetName())); + if (IsFormatAvailable(ui::ClipboardFormatType::GetRtfType(), buffer, data_dst)) + types.push_back(base::UTF8ToUTF16(ui::ClipboardFormatType::GetRtfType().GetName())); + if (IsFormatAvailable(ui::ClipboardFormatType::GetBitmapType(), buffer, data_dst)) + types.push_back(base::UTF8ToUTF16(ui::kMimeTypePNG)); + if (IsFormatAvailable(ui::ClipboardFormatType::GetSvgType(), buffer, data_dst)) + types.push_back(base::UTF8ToUTF16(ui::kMimeTypeSvg)); + + return types; } } // namespace QtWebEngineCore diff --git a/src/core/clipboard_qt.h b/src/core/clipboard_qt.h index 7884da167..b4c9d4c7d 100644 --- a/src/core/clipboard_qt.h +++ b/src/core/clipboard_qt.h @@ -44,27 +44,43 @@ namespace QtWebEngineCore { -class ClipboardQt : public ui::Clipboard { +class ClipboardQt : public ui::Clipboard +{ public: - uint64_t GetSequenceNumber(ui::ClipboardType type) const override; - bool IsFormatAvailable(const ui::ClipboardFormatType &format, ui::ClipboardType type) const override; - void Clear(ui::ClipboardType type) override; - void ReadAvailableTypes(ui::ClipboardType type, std::vector<base::string16> *types, - bool *contains_filenames) const override; - void ReadText(ui::ClipboardType type, base::string16 *result) const override; - void ReadAsciiText(ui::ClipboardType type, std::string *result) const override; - void ReadHTML(ui::ClipboardType type, base::string16 *markup, std::string *src_url, uint32_t *fragment_start, + uint64_t GetSequenceNumber(ui::ClipboardBuffer type) const override; + bool IsFormatAvailable(const ui::ClipboardFormatType &format, + ui::ClipboardBuffer buffer, + const ui::ClipboardDataEndpoint *data_dst) const override; + void Clear(ui::ClipboardBuffer type) override; + void ReadAvailableTypes(ui::ClipboardBuffer type, + const ui::ClipboardDataEndpoint *data_dst, + std::vector<base::string16> *types) const override; + void ReadText(ui::ClipboardBuffer type, const ui::ClipboardDataEndpoint *data_dst, base::string16 *result) const override; + void ReadAsciiText(ui::ClipboardBuffer type, const ui::ClipboardDataEndpoint *data_dst, std::string *result) const override; + void ReadHTML(ui::ClipboardBuffer type, const ui::ClipboardDataEndpoint *data_dst, base::string16 *markup, std::string *src_url, uint32_t *fragment_start, uint32_t *fragment_end) const override; - void ReadRTF(ui::ClipboardType type, std::string *result) const override; - SkBitmap ReadImage(ui::ClipboardType type) const override; - void ReadCustomData(ui::ClipboardType clipboard_type, const base::string16 &type, base::string16 *result) const override; - void ReadBookmark(base::string16 *title, std::string *url) const override; - void ReadData(const ui::ClipboardFormatType &format, std::string *result) const override; - + void ReadRTF(ui::ClipboardBuffer type, const ui::ClipboardDataEndpoint *data_dst, std::string *result) const override; + void ReadImage(ui::ClipboardBuffer buffer, const ui::ClipboardDataEndpoint *data_dst, ReadImageCallback callback) const override; + void ReadCustomData(ui::ClipboardBuffer clipboard_type, const base::string16 &type, const ui::ClipboardDataEndpoint *data_dst, base::string16 *result) const override; + void ReadBookmark(const ui::ClipboardDataEndpoint *data_dst, base::string16 *title, std::string *url) const override; + void ReadData(const ui::ClipboardFormatType &format, const ui::ClipboardDataEndpoint *data_dst, std::string *result) const override; +#if defined(USE_OZONE) + bool IsSelectionBufferAvailable() const override; +#endif void OnPreShutdown() override {} + void ReadSvg(ui::ClipboardBuffer, const ui::ClipboardDataEndpoint *, base::string16 *) const override; + void WriteSvg(const char *, size_t) override; + std::vector<base::string16> ReadAvailablePlatformSpecificFormatNames(ui::ClipboardBuffer buffer, const ui::ClipboardDataEndpoint *data_dst) const override; protected: - void WriteObjects(ui::ClipboardType type, const ObjectMap &objects) override; + void WritePortableRepresentations( + ui::ClipboardBuffer buffer, + const ObjectMap &objects, + std::unique_ptr<ui::ClipboardDataEndpoint> data_src) override; + void WritePlatformRepresentations( + ui::ClipboardBuffer buffer, + std::vector<Clipboard::PlatformRepresentation> platform_representations, + std::unique_ptr<ui::ClipboardDataEndpoint> data_src) override; void WriteText(const char *text_data, size_t text_len) override; void WriteHTML(const char *markup_data, size_t markup_len, const char *url_data, size_t url_len) override; void WriteRTF(const char *rtf_data, size_t data_len) override; diff --git a/src/core/command_line_pref_store_qt.cpp b/src/core/command_line_pref_store_qt.cpp deleted file mode 100644 index 5c5c82e1a..000000000 --- a/src/core/command_line_pref_store_qt.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "command_line_pref_store_qt.h" - -#include "chrome/common/chrome_switches.h" -#include "components/proxy_config/proxy_config_dictionary.h" -#include "components/proxy_config/proxy_config_pref_names.h" -#include "content/public/common/content_switches.h" -#include <QDebug> - -CommandLinePrefStoreQt::CommandLinePrefStoreQt(const base::CommandLine *commandLine) - : CommandLinePrefStore(commandLine) -{ - - if (commandLine->HasSwitch(switches::kNoProxyServer)) { - SetValue(proxy_config::prefs::kProxy, - std::make_unique<base::Value>(ProxyConfigDictionary::CreateDirect()), - WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); - } else if (commandLine->HasSwitch(switches::kProxyPacUrl)) { - std::string pac_script_url = - commandLine->GetSwitchValueASCII(switches::kProxyPacUrl); - SetValue(proxy_config::prefs::kProxy, - std::make_unique<base::Value>(ProxyConfigDictionary::CreatePacScript( - pac_script_url, false)), - WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); - } else if (commandLine->HasSwitch(switches::kProxyAutoDetect)) { - SetValue(proxy_config::prefs::kProxy, - std::make_unique<base::Value>( - ProxyConfigDictionary::CreateAutoDetect()), - WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); - } else if (commandLine->HasSwitch(switches::kProxyServer)) { - std::string proxy_server = - commandLine->GetSwitchValueASCII(switches::kProxyServer); - std::string bypass_list = - commandLine->GetSwitchValueASCII(switches::kProxyBypassList); - SetValue( - proxy_config::prefs::kProxy, - std::make_unique<base::Value>(ProxyConfigDictionary::CreateFixedServers( - proxy_server, bypass_list)), - WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); - } - - if (commandLine->HasSwitch(switches::kNoProxyServer) && (commandLine->HasSwitch(switches::kProxyAutoDetect) || commandLine->HasSwitch(switches::kProxyServer) || commandLine->HasSwitch(switches::kProxyPacUrl) || commandLine->HasSwitch(switches::kProxyBypassList))) { - qWarning("Additional command-line proxy switches specified when --%s was also specified", - qPrintable(switches::kNoProxyServer)); - } -} - -CommandLinePrefStoreQt::~CommandLinePrefStoreQt() = default; diff --git a/src/core/common/extensions/api/qtwebengine_extensions_features.gni b/src/core/common/extensions/api/qtwebengine_extensions_features.gni index ed7e713c6..3873e235a 100644 --- a/src/core/common/extensions/api/qtwebengine_extensions_features.gni +++ b/src/core/common/extensions/api/qtwebengine_extensions_features.gni @@ -12,7 +12,8 @@ json_features("qt_permission_features") { feature_type = "PermissionFeature" method_name = "AddQtPermissionFeatures" sources = [ - "//extensions/common/api/_permission_features.json" + "//chrome/common/extensions/api/_permission_features.json", + "//extensions/common/api/_permission_features.json", ] } @@ -20,6 +21,7 @@ group("qtwebengine_extensions_features") { public_deps = [ ":qt_api_features", ":qt_permission_features", + "//chrome/common/extensions/api:extensions_features", "//extensions/common/api:extensions_features", ] } diff --git a/src/core/common/extensions/extensions_api_provider_qt.cpp b/src/core/common/extensions/extensions_api_provider_qt.cpp index 22154a9d1..81eb76f3e 100644 --- a/src/core/common/extensions/extensions_api_provider_qt.cpp +++ b/src/core/common/extensions/extensions_api_provider_qt.cpp @@ -39,6 +39,8 @@ #include "extensions_api_provider_qt.h" +#include "chrome/common/extensions/permissions/chrome_api_permissions.h" +#include "chrome/common/extensions/api/generated_schemas.h" #include "chrome/grit/common_resources.h" #include "extensions/common/api/api_features.h" @@ -51,6 +53,7 @@ #include "extensions/common/features/json_feature_provider_source.h" #include "extensions/common/permissions/permissions_info.h" #include "extensions/grit/extensions_resources.h" +#include "qtwebengine/common/extensions/api/generated_schemas.h" #include "qt_api_features.h" //#include "qt_behavior_features.h" @@ -85,16 +88,30 @@ void ExtensionsAPIProviderQt::AddPermissionFeatures(FeatureProvider *provider) bool ExtensionsAPIProviderQt::IsAPISchemaGenerated(const std::string &name) { - return api::GeneratedSchemas::IsGenerated(name); + return api::GeneratedSchemas::IsGenerated(name) || + api::ChromeGeneratedSchemas::IsGenerated(name) || + api::QtWebEngineGeneratedSchemas::IsGenerated(name); } base::StringPiece ExtensionsAPIProviderQt::GetAPISchema(const std::string &name) { - return api::GeneratedSchemas::Get(name); + if (!api::GeneratedSchemas::Get(name).empty()) + return api::GeneratedSchemas::Get(name); + + if (!api::ChromeGeneratedSchemas::Get(name).empty()) + return api::ChromeGeneratedSchemas::Get(name); + + if (!api::QtWebEngineGeneratedSchemas::Get(name).empty()) + return api::QtWebEngineGeneratedSchemas::Get(name); + + return ""; } void ExtensionsAPIProviderQt::RegisterPermissions(PermissionsInfo* permissions_info) { + permissions_info->RegisterPermissions( + chrome_api_permissions::GetPermissionInfos(), + chrome_api_permissions::GetPermissionAliases()); } } diff --git a/src/core/common/extensions/extensions_client_qt.cpp b/src/core/common/extensions/extensions_client_qt.cpp index dd1de1483..c4cc2321a 100644 --- a/src/core/common/extensions/extensions_client_qt.cpp +++ b/src/core/common/extensions/extensions_client_qt.cpp @@ -108,18 +108,18 @@ void ExtensionsClientQt::FilterHostPermissions(const URLPatternSet &hosts, { } -// Replaces the scripting whitelist with |whitelist|. Used in the renderer{} +// Replaces the scripting allowlist with |allowlist|. Used in the renderer{} // only used for testing in the browser process. -void ExtensionsClientQt::SetScriptingWhitelist(const ExtensionsClient::ScriptingWhitelist &whitelist) +void ExtensionsClientQt::SetScriptingAllowlist(const ExtensionsClient::ScriptingAllowlist &allowlist) { - scripting_whitelist_ = whitelist; + scripting_allowlist_ = allowlist; } -// Return the whitelist of extensions that can run content scripts on +// Return the allowlist of extensions that can run content scripts on // any origin. -const ExtensionsClient::ScriptingWhitelist &ExtensionsClientQt::GetScriptingWhitelist() const +const ExtensionsClient::ScriptingAllowlist &ExtensionsClientQt::GetScriptingAllowlist() const { - return scripting_whitelist_; + return scripting_allowlist_; } // Get the set of chrome:// hosts that |extension| can run content scripts on. diff --git a/src/core/common/extensions/extensions_client_qt.h b/src/core/common/extensions/extensions_client_qt.h index e689f76b7..2466e14e3 100644 --- a/src/core/common/extensions/extensions_client_qt.h +++ b/src/core/common/extensions/extensions_client_qt.h @@ -87,13 +87,13 @@ public: URLPatternSet *new_hosts, PermissionIDSet *permissions) const override; - // Replaces the scripting whitelist with |whitelist|. Used in the renderer; + // Replaces the scripting allowlist with |allowlist|. Used in the renderer; // only used for testing in the browser process. - void SetScriptingWhitelist(const ScriptingWhitelist &whitelist) override; + void SetScriptingAllowlist(const ScriptingAllowlist &allowlist) override; - // Return the whitelist of extensions that can run content scripts on + // Return the allowlist of extensions that can run content scripts on // any origin. - const ScriptingWhitelist &GetScriptingWhitelist() const override; + const ScriptingAllowlist &GetScriptingAllowlist() const override; // Get the set of chrome:// hosts that |extension| can run content scripts on. URLPatternSet GetPermittedChromeSchemeHosts(const Extension *extension, @@ -127,7 +127,7 @@ public: static ExtensionsClientQt *GetInstance(); private: - ScriptingWhitelist scripting_whitelist_; + ScriptingAllowlist scripting_allowlist_; const ChromePermissionMessageProvider permission_message_provider_; mutable GURL update_url_; mutable GURL base_url_; diff --git a/src/core/common/qt_messages.h b/src/core/common/qt_messages.h index b99204b74..ebf49e8c3 100644 --- a/src/core/common/qt_messages.h +++ b/src/core/common/qt_messages.h @@ -9,20 +9,6 @@ #include "content/public/common/webplugininfo.h" #include "ipc/ipc_message_macros.h" #include "ppapi/buildflags/buildflags.h" -#include "user_script_data.h" - -IPC_STRUCT_TRAITS_BEGIN(UserScriptData) - IPC_STRUCT_TRAITS_MEMBER(source) - IPC_STRUCT_TRAITS_MEMBER(url) - IPC_STRUCT_TRAITS_MEMBER(injectionPoint) - IPC_STRUCT_TRAITS_MEMBER(injectForSubframes) - IPC_STRUCT_TRAITS_MEMBER(worldId) - IPC_STRUCT_TRAITS_MEMBER(scriptId) - IPC_STRUCT_TRAITS_MEMBER(globs) - IPC_STRUCT_TRAITS_MEMBER(excludeGlobs) - IPC_STRUCT_TRAITS_MEMBER(urlPatterns) -IPC_STRUCT_TRAITS_END() - #define IPC_MESSAGE_START QtMsgStart @@ -30,87 +16,41 @@ IPC_STRUCT_TRAITS_END() // RenderView messages // These are messages sent from the browser to the renderer process. -IPC_MESSAGE_ROUTED1(RenderViewObserverQt_FetchDocumentMarkup, - uint64_t /* requestId */) - -IPC_MESSAGE_ROUTED1(RenderViewObserverQt_FetchDocumentInnerText, - uint64_t /* requestId */) - -// User scripts messages -IPC_MESSAGE_ROUTED1(RenderFrameObserverHelper_AddScript, - UserScriptData /* script */) -IPC_MESSAGE_ROUTED1(RenderFrameObserverHelper_RemoveScript, - UserScriptData /* script */) -IPC_MESSAGE_ROUTED0(RenderFrameObserverHelper_ClearScripts) - -IPC_MESSAGE_CONTROL1(UserResourceController_AddScript, UserScriptData /* scriptContents */) -IPC_MESSAGE_CONTROL1(UserResourceController_RemoveScript, UserScriptData /* scriptContents */) -IPC_MESSAGE_CONTROL0(UserResourceController_ClearScripts) - -// Tells the renderer whether or not a file system access has been allowed. -IPC_MESSAGE_ROUTED2(QtWebEngineMsg_RequestFileSystemAccessAsyncResponse, +// Tells the renderer whether or not a storage access has been allowed. +IPC_MESSAGE_ROUTED2(QtWebEngineMsg_RequestStorageAccessAsyncResponse, int /* request_id */, bool /* allowed */) - //----------------------------------------------------------------------------- // WebContents messages // These are messages sent from the renderer back to the browser process. -IPC_MESSAGE_ROUTED2(RenderViewObserverHostQt_DidFetchDocumentMarkup, - uint64_t /* requestId */, - base::string16 /* markup */) - -IPC_MESSAGE_ROUTED2(RenderViewObserverHostQt_DidFetchDocumentInnerText, - uint64_t /* requestId */, - base::string16 /* innerText */) - -IPC_MESSAGE_ROUTED1(RenderViewObserverQt_SetBackgroundColor, - uint32_t /* color */) - IPC_MESSAGE_ROUTED0(RenderViewObserverHostQt_DidFirstVisuallyNonEmptyLayout) //----------------------------------------------------------------------------- // Misc messages // These are messages sent from the renderer to the browser process. -// Sent by the renderer process to check whether access to web databases is -// granted by content settings. -IPC_SYNC_MESSAGE_CONTROL3_1(QtWebEngineHostMsg_AllowDatabase, +IPC_SYNC_MESSAGE_CONTROL4_1(QtWebEngineHostMsg_AllowStorageAccess, int /* render_frame_id */, GURL /* origin_url */, GURL /* top origin url */, + int /* storage_type */, bool /* allowed */) -// Sent by the renderer process to check whether access to DOM Storage is -// granted by content settings. -IPC_SYNC_MESSAGE_CONTROL4_1(QtWebEngineHostMsg_AllowDOMStorage, +IPC_SYNC_MESSAGE_CONTROL4_1(QtWebEngineHostMsg_RequestStorageAccessSync, int /* render_frame_id */, GURL /* origin_url */, GURL /* top origin url */, - bool /* if true local storage, otherwise session */, + int /* storage_type */, bool /* allowed */) -// Sent by the renderer process to check whether access to FileSystem is +// Sent by the renderer process to check whether access to storage is // granted by content settings. -IPC_SYNC_MESSAGE_CONTROL3_1(QtWebEngineHostMsg_RequestFileSystemAccessSync, - int /* render_frame_id */, - GURL /* origin_url */, - GURL /* top origin url */, - bool /* allowed */) - -// Sent by the renderer process to check whether access to FileSystem is -// granted by content settings. -IPC_MESSAGE_CONTROL4(QtWebEngineHostMsg_RequestFileSystemAccessAsync, +IPC_MESSAGE_CONTROL5(QtWebEngineHostMsg_RequestStorageAccessAsync, int /* render_frame_id */, int /* request_id */, GURL /* origin_url */, - GURL /* top origin url */) + GURL /* top origin url */, + int /* storage_type */) -// Sent by the renderer process to check whether access to Indexed DB is -// granted by content settings. -IPC_SYNC_MESSAGE_CONTROL3_1(QtWebEngineHostMsg_AllowIndexedDB, - int /* render_frame_id */, - GURL /* origin_url */, - GURL /* top origin url */, - bool /* allowed */) diff --git a/src/core/common/user_script_data.h b/src/core/common/user_script_data.h deleted file mode 100644 index 8d98890e3..000000000 --- a/src/core/common/user_script_data.h +++ /dev/null @@ -1,74 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef USER_SCRIPT_DATA_H -#define USER_SCRIPT_DATA_H - -#include <QtCore/QHash> -#include <string> -#include "ipc/ipc_message_utils.h" -#include "url/gurl.h" - -struct UserScriptData { - enum InjectionPoint { - AfterLoad, - DocumentLoadFinished, - DocumentElementCreation - }; - - UserScriptData(); - - std::string source; - GURL url; - /*InjectionPoint*/uint8_t injectionPoint; - bool injectForSubframes; - uint worldId; - uint64_t scriptId; - std::vector<std::string> globs; - std::vector<std::string> excludeGlobs; - std::vector<std::string> urlPatterns; -}; - -QT_BEGIN_NAMESPACE - -Q_DECLARE_TYPEINFO(UserScriptData, Q_MOVABLE_TYPE); - -QT_END_NAMESPACE - -#endif // USER_SCRIPT_DATA_H diff --git a/src/core/compositor/chromium_gpu_helper.cpp b/src/core/compositor/chromium_gpu_helper.cpp deleted file mode 100644 index 71d0f3687..000000000 --- a/src/core/compositor/chromium_gpu_helper.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE.Chromium file. - -#include "chromium_gpu_helper.h" - -// Some headers include the namespace ws, and can not coexist with -// Qt headers that include QTextStream, which includes most QSG headers -// via QMatrix4x4. -#include "content/browser/renderer_host/render_widget_host_impl.h" - -// Including gpu/command_buffer headers before content/gpu headers makes sure that -// guards are defined to prevent duplicate definition errors with forward declared -// GL typedefs cascading through content header includes. -#include "gpu/command_buffer/service/mailbox_manager.h" -#include "gpu/command_buffer/service/texture_base.h" - -#include "content/gpu/gpu_child_thread.h" -#include "gpu/ipc/service/gpu_channel_manager.h" - -#ifdef Q_OS_QNX -#include "content/common/gpu/stream_texture_qnx.h" -#endif - -scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner() -{ - return content::GpuChildThread::instance()->main_thread_runner(); -} - -gpu::MailboxManager *mailbox_manager() -{ - gpu::GpuChannelManager *gpuChannelManager = content::GpuChildThread::instance()->gpu_channel_manager(); - return gpuChannelManager->mailbox_manager(); -} - -gpu::TextureBase* ConsumeTexture(gpu::MailboxManager *mailboxManager, unsigned target, const gpu::Mailbox& mailbox) -{ - Q_UNUSED(target); - return mailboxManager->ConsumeTexture(mailbox); -} - -unsigned int service_id(gpu::TextureBase *tex) -{ - return tex->service_id(); -} - -void ProgressFlingIfNeeded(content::RenderWidgetHost *host, const base::TimeTicks ¤t_time) -{ - content::RenderWidgetHostImpl::From(host)->ProgressFlingIfNeeded(current_time); -} - -#ifdef Q_OS_QNX -EGLStreamData eglstream_connect_consumer(gpu::Texture *tex) -{ - EGLStreamData egl_stream; - content::StreamTexture* image = static_cast<content::StreamTexture *>(tex->GetLevelImage(GL_TEXTURE_EXTERNAL_OES, 0)); - if (image) { - image->ConnectConsumerIfNeeded(&egl_stream.egl_display, &egl_stream.egl_str_handle); - } - return egl_stream; -} -#endif diff --git a/src/core/compositor/compositor.cpp b/src/core/compositor/compositor.cpp deleted file mode 100644 index 1578e431e..000000000 --- a/src/core/compositor/compositor.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "compositor.h" - -#include "compositor_resource_tracker.h" -#include "delegated_frame_node.h" - -#include "base/task/post_task.h" -#include "components/viz/common/resources/returned_resource.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" -#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h" - -namespace QtWebEngineCore { - -Compositor::Compositor(content::RenderWidgetHost *host) - : m_resourceTracker(new CompositorResourceTracker) - , m_host(host) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - m_taskRunner = base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::UI, base::TaskPriority::USER_VISIBLE}); - m_beginFrameSource = - std::make_unique<viz::DelayBasedBeginFrameSource>( - std::make_unique<viz::DelayBasedTimeSource>(m_taskRunner.get()), - viz::BeginFrameSource::kNotRestartableId); -} - -Compositor::~Compositor() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); -} - -void Compositor::setFrameSinkClient(viz::mojom::CompositorFrameSinkClient *frameSinkClient) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - if (m_frameSinkClient == frameSinkClient) - return; - - // Accumulated resources belong to the old RendererCompositorFrameSink and - // should not be returned. - // - // TODO(juvaldma): Can there be a pending frame from the old client? - m_resourceTracker->returnResources(); - m_frameSinkClient = frameSinkClient; -} - -void Compositor::setNeedsBeginFrames(bool needsBeginFrames) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - if (m_needsBeginFrames == needsBeginFrames) - return; - - if (needsBeginFrames) - m_beginFrameSource->AddObserver(this); - else - m_beginFrameSource->RemoveObserver(this); - - m_needsBeginFrames = needsBeginFrames; -} - -void Compositor::submitFrame(viz::CompositorFrame frame, base::OnceClosure callback) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK(!m_submitCallback); - - m_pendingFrame = std::move(frame); - m_submitCallback = std::move(callback); - m_resourceTracker->submitResources( - m_pendingFrame, - base::BindOnce(&Compositor::runSubmitCallback, base::Unretained(this))); -} - -QSGNode *Compositor::updatePaintNode(QSGNode *oldNode, RenderWidgetHostViewQtDelegate *viewDelegate) -{ - // DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - // - // This might be called from a Qt Quick render thread, but the UI thread - // will still be blocked for the duration of this call. - - DelegatedFrameNode *frameNode = static_cast<DelegatedFrameNode *>(oldNode); - if (!frameNode) - frameNode = new DelegatedFrameNode; - - if (!m_updatePaintNodeShouldCommit) { - frameNode->commit(m_committedFrame, viz::CompositorFrame(), m_resourceTracker.get(), viewDelegate); - return frameNode; - } - m_updatePaintNodeShouldCommit = false; - - gfx::PresentationFeedback dummyFeedback(base::TimeTicks::Now(), base::TimeDelta(), gfx::PresentationFeedback::Flags::kVSync); - m_presentations.emplace(m_committedFrame.metadata.frame_token, viz::FrameTimingDetails{dummyFeedback}); - - m_resourceTracker->commitResources(); - frameNode->commit(m_pendingFrame, m_committedFrame, m_resourceTracker.get(), viewDelegate); - m_committedFrame = std::move(m_pendingFrame); - m_pendingFrame = viz::CompositorFrame(); - - m_taskRunner->PostTask(FROM_HERE, - base::BindOnce(&Compositor::notifyFrameCommitted, m_weakPtrFactory.GetWeakPtr())); - - return frameNode; -} - -void Compositor::runSubmitCallback() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - m_updatePaintNodeShouldCommit = true; - std::move(m_submitCallback).Run(); -} - -void Compositor::notifyFrameCommitted() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - m_beginFrameSource->DidFinishFrame(this); - if (m_frameSinkClient) - m_frameSinkClient->DidReceiveCompositorFrameAck(m_resourceTracker->returnResources()); -} - -void Compositor::sendPresentationFeedback(uint frame_token) -{ - gfx::PresentationFeedback dummyFeedback(base::TimeTicks::Now(), base::TimeDelta(), gfx::PresentationFeedback::Flags::kVSync); - viz::FrameTimingDetails dummyDetails = {dummyFeedback}; - m_presentations.emplace(frame_token, dummyDetails); -} - -bool Compositor::OnBeginFrameDerivedImpl(const viz::BeginFrameArgs &args) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - ProgressFlingIfNeeded(m_host, args.frame_time); - m_beginFrameSource->OnUpdateVSyncParameters(args.frame_time, args.interval); - if (m_frameSinkClient) { - m_frameSinkClient->OnBeginFrame(args, m_presentations); - m_presentations.clear(); - } - - return true; -} - -void Compositor::OnBeginFrameSourcePausedChanged(bool) -{ - // Ignored for now. If the begin frame source is paused, the renderer - // doesn't need to be informed about it and will just not receive more - // begin frames. -} - -} // namespace QtWebEngineCore diff --git a/src/core/compositor/compositor.h b/src/core/compositor/compositor.h deleted file mode 100644 index 36e62c17a..000000000 --- a/src/core/compositor/compositor.h +++ /dev/null @@ -1,131 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef COMPOSITOR_H -#define COMPOSITOR_H - -#include "base/memory/weak_ptr.h" -#include "components/viz/common/frame_timing_details.h" -#include "components/viz/common/frame_sinks/begin_frame_source.h" -#include "components/viz/common/quads/compositor_frame.h" - -#include <QtCore/qglobal.h> -#include <QtCore/qshareddata.h> - -#include <QtCore/qglobal.h> -#include <QtCore/qshareddata.h> - -QT_BEGIN_NAMESPACE -class QSGNode; -QT_END_NAMESPACE - -namespace content { -class RenderWidgetHost; -} -namespace viz { -struct ReturnedResource; -namespace mojom { -class CompositorFrameSinkClient; -} // namespace mojom -} // namespace viz - -namespace QtWebEngineCore { - -class CompositorResourceTracker; -class RenderWidgetHostViewQtDelegate; - -// Receives viz::CompositorFrames from child compositors and provides QSGNodes -// to the Qt Quick renderer. -// -// The life cycle of a frame: -// -// Step 1. A new CompositorFrame is received from child compositors and handed -// off to submitFrame(). The new frame will start off in a pending state. -// -// Step 2. Once the new frame is ready to be rendered, Compositor will notify -// the client by running the callback given to submitFrame(). -// -// Step 3. Once the client is ready to render, updatePaintNode() should be -// called to receive the scene graph for the new frame. This call will commit -// the pending frame. Until the next frame is ready, all subsequent calls to -// updatePaintNode() will keep using this same committed frame. -// -// Step 4. The Compositor will return unneeded resources back to the child -// compositors. Go to step 1. -class Compositor final : private viz::BeginFrameObserverBase -{ -public: - explicit Compositor(content::RenderWidgetHost *host); - ~Compositor() override; - - void setFrameSinkClient(viz::mojom::CompositorFrameSinkClient *frameSinkClient); - void setNeedsBeginFrames(bool needsBeginFrames); - - void submitFrame(viz::CompositorFrame frame, base::OnceClosure callback); - QSGNode *updatePaintNode(QSGNode *oldNode, RenderWidgetHostViewQtDelegate *viewDelegate); - -private: - void runSubmitCallback(); - void notifyFrameCommitted(); - void sendPresentationFeedback(uint frame_token); - - // viz::BeginFrameObserverBase - bool OnBeginFrameDerivedImpl(const viz::BeginFrameArgs &args) override; - void OnBeginFrameSourcePausedChanged(bool paused) override; - - viz::CompositorFrame m_committedFrame; - viz::CompositorFrame m_pendingFrame; - base::OnceClosure m_submitCallback; - std::unique_ptr<CompositorResourceTracker> m_resourceTracker; - content::RenderWidgetHost *m_host; - std::unique_ptr<viz::SyntheticBeginFrameSource> m_beginFrameSource; - base::flat_map<uint32_t, viz::FrameTimingDetails> m_presentations; - viz::mojom::CompositorFrameSinkClient *m_frameSinkClient = nullptr; - bool m_updatePaintNodeShouldCommit = false; - bool m_needsBeginFrames = false; - - scoped_refptr<base::SingleThreadTaskRunner> m_taskRunner; - base::WeakPtrFactory<Compositor> m_weakPtrFactory{this}; - - DISALLOW_COPY_AND_ASSIGN(Compositor); -}; - -} // namespace QtWebEngineCore - -#endif // !COMPOSITOR_H diff --git a/src/core/compositor/compositor_resource.h b/src/core/compositor/compositor_resource.h deleted file mode 100644 index f7df2ab59..000000000 --- a/src/core/compositor/compositor_resource.h +++ /dev/null @@ -1,123 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef COMPOSITOR_RESOURCE_H -#define COMPOSITOR_RESOURCE_H - -#include <base/memory/ref_counted.h> -#include <components/viz/common/resources/transferable_resource.h> - -#include <QtCore/qglobal.h> -#include <QtGui/qtgui-config.h> - -#if QT_CONFIG(opengl) -# include "compositor_resource_fence.h" -#endif - -namespace viz { -class SharedBitmap; -} // namespace viz - -namespace QtWebEngineCore { - -using CompositorResourceId = quint32; - -// A resource (OpenGL texture or software shared bitmap). -// -// - Created by the CompositorResourceTracker from a newly submitted -// CompositorFrame's resource_list. -// -// - Until the frame is committed, its resources are in a 'pending' state and -// are inaccessible from outside the CompositorResourceTracker. -// -// - Once the frame is committed, its resources can be found via -// CompositorResourceTracker::findResource. -// -// - A committed resource's fields may not be updated and are safe to use from -// other threads without synchronization (unless noted otherwise). -class CompositorResource : public viz::TransferableResource -{ -public: - CompositorResource(const viz::TransferableResource &tr) : viz::TransferableResource(tr) {} - - // Counts the number of times this resource has been encountered in - // CompositorFrames' resource lists. - // - // Corresponds to viz::ReturnedResource::count. - // - // Updated by CompositorResourceTracker on UI thread. - int import_count = 1; - - // Identifies the last frame that needed this resource. Used by - // CompositorResourceTracker to return unused resources back to child - // compositors. - // - // Updated by CompositorResourceTracker on UI thread. - quint32 last_used_for_frame = 0; - - // Bitmap (if is_software). - std::unique_ptr<viz::SharedBitmap> bitmap; - -#if QT_CONFIG(opengl) - // OpenGL texture id (if !is_software). - quint32 texture_id = 0; - - // Should be waited on before using the texture (non-null if !is_software). - scoped_refptr<CompositorResourceFence> texture_fence; -#endif // QT_CONFIG(opengl) -}; - -inline bool operator<(const CompositorResource &r1, const CompositorResource &r2) -{ - return r1.id < r2.id; -} - -inline bool operator<(const CompositorResource &r, CompositorResourceId id) -{ - return r.id < id; -} - -inline bool operator<(CompositorResourceId id, const CompositorResource &r) -{ - return id < r.id; -} - -} // namespace QtWebEngineCore - -#endif // !COMPOSITOR_RESOURCE_H diff --git a/src/core/compositor/compositor_resource_fence.cpp b/src/core/compositor/compositor_resource_fence.cpp index 4179395d6..e7bf2fea7 100644 --- a/src/core/compositor/compositor_resource_fence.cpp +++ b/src/core/compositor/compositor_resource_fence.cpp @@ -38,15 +38,22 @@ ****************************************************************************/ #include "compositor_resource_fence.h" - +#include "ozone/gl_surface_qt.h" #include "ui/gl/gl_context.h" +#include <QtGui/private/qtguiglobal_p.h> #include <QtGui/qopenglcontext.h> #ifndef GL_TIMEOUT_IGNORED #define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull #endif + +#if QT_CONFIG(egl) +#include <EGL/egl.h> +#include <EGL/eglext.h> +#endif + namespace QtWebEngineCore { void CompositorResourceFence::wait() diff --git a/src/core/compositor/compositor_resource_tracker.cpp b/src/core/compositor/compositor_resource_tracker.cpp deleted file mode 100644 index 741c2717c..000000000 --- a/src/core/compositor/compositor_resource_tracker.cpp +++ /dev/null @@ -1,266 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "compositor_resource_tracker.h" - -#include "chromium_gpu_helper.h" -#include "render_widget_host_view_qt_delegate.h" -#include "web_engine_context.h" - -#include "base/message_loop/message_loop.h" -#include "base/task/post_task.h" -#include "components/viz/common/quads/compositor_frame.h" -#include "components/viz/common/resources/returned_resource.h" -#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h" -#include "content/browser/browser_main_loop.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/gpu/content_gpu_client.h" -#include "gpu/command_buffer/service/mailbox_manager.h" -#include "gpu/command_buffer/service/sync_point_manager.h" - -namespace QtWebEngineCore { - -CompositorResourceTracker::CompositorResourceTracker() -{} - -CompositorResourceTracker::~CompositorResourceTracker() -{} - -void CompositorResourceTracker::submitResources(const viz::CompositorFrame &frame, base::OnceClosure callback) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK(!m_submitCallback); - DCHECK(m_pendingResources.empty()); - DCHECK(m_pendingImports.empty()); - DCHECK(m_pendingResourceUpdates == 0); - - m_submitCallback = std::move(callback); - - m_pendingResources.reserve(frame.resource_list.size()); - m_pendingImports.reserve(frame.resource_list.size()); - - for (const viz::TransferableResource &transferableResource : frame.resource_list) { - auto it = m_committedResources.find(transferableResource.id); - if (it != m_committedResources.end()) - m_pendingImports.push_back(&*it); - else - m_pendingResources.emplace_back(transferableResource); - } - - if (m_pendingResources.empty()) { - scheduleRunSubmitCallback(); - return; - } - - m_pendingResourceUpdates = m_pendingResources.size(); - - std::vector<CompositorResource *> batch; - batch.reserve(m_pendingResources.size()); - - for (CompositorResource &resource : m_pendingResources) { - if (resource.is_software) - updateBitmap(&resource); - else if (!scheduleUpdateMailbox(&resource)) - batch.push_back(&resource); - } - - if (!batch.empty()) - scheduleUpdateMailboxes(std::move(batch)); -} - -void CompositorResourceTracker::commitResources() -{ - // DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - // - // This might be called from a Qt Quick render thread, but the UI thread - // will still be blocked for the duration of this call. - - DCHECK(m_pendingResourceUpdates == 0); - - for (CompositorResource *resource : m_pendingImports) - resource->import_count++; - m_pendingImports.clear(); - - m_committedResources.insert(std::make_move_iterator(m_pendingResources.begin()), - std::make_move_iterator(m_pendingResources.end())); - m_pendingResources.clear(); - - ++m_committedFrameId; -} - -std::vector<viz::ReturnedResource> CompositorResourceTracker::returnResources() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - std::vector<viz::ReturnedResource> returnedResources; - base::EraseIf(m_committedResources, [&](const CompositorResource &resource) { - if (resource.last_used_for_frame != m_committedFrameId) { - viz::ReturnedResource returnedResource; - returnedResource.id = resource.id; - returnedResource.count = resource.import_count; - returnedResources.push_back(std::move(returnedResource)); - return true; - } - return false; - }); - return returnedResources; -} - -const CompositorResource *CompositorResourceTracker::findResource(CompositorResourceId id) const -{ - auto it = m_committedResources.find(id); - DCHECK(it != m_committedResources.end()); - - const_cast<CompositorResource &>(*it).last_used_for_frame = m_committedFrameId; - - return &*it; -} - -void CompositorResourceTracker::updateBitmap(CompositorResource *resource) -{ - content::BrowserMainLoop *browserMainLoop = content::BrowserMainLoop::GetInstance(); - viz::ServerSharedBitmapManager *bitmapManager = browserMainLoop->GetServerSharedBitmapManager(); - - resource->bitmap = bitmapManager->GetSharedBitmapFromId( - resource->size, - viz::BGRA_8888, - resource->mailbox_holder.mailbox); - - if (--m_pendingResourceUpdates == 0) - scheduleRunSubmitCallback(); -} - -quint32 CompositorResourceTracker::consumeMailbox(const gpu::MailboxHolder &mailboxHolder) -{ -#if QT_CONFIG(opengl) - gpu::MailboxManager *mailboxManager = mailbox_manager(); - DCHECK(mailboxManager); - if (mailboxHolder.sync_token.HasData()) - mailboxManager->PullTextureUpdates(mailboxHolder.sync_token); - gpu::TextureBase *tex = mailboxManager->ConsumeTexture(mailboxHolder.mailbox); - return tex ? service_id(tex) : 0; -#else - NOTREACHED(); -#endif // QT_CONFIG(OPENGL) -} - -bool CompositorResourceTracker::scheduleUpdateMailbox(CompositorResource *resource) -{ -#if QT_CONFIG(opengl) - gpu::SyncPointManager *syncPointManager = WebEngineContext::syncPointManager(); - DCHECK(syncPointManager); - return syncPointManager->WaitOutOfOrder( - resource->mailbox_holder.sync_token, - base::BindOnce(&CompositorResourceTracker::updateMailbox, - m_weakPtrFactory.GetWeakPtr(), - resource)); -#else - NOTREACHED(); -#endif // QT_CONFIG(OPENGL) -} - -void CompositorResourceTracker::updateMailbox(CompositorResource *resource) -{ -#if QT_CONFIG(opengl) - resource->texture_id = consumeMailbox(resource->mailbox_holder); - resource->texture_fence = CompositorResourceFence::create(); - - if (--m_pendingResourceUpdates == 0) - scheduleRunSubmitCallback(); -#else - NOTREACHED(); -#endif // QT_CONFIG(OPENGL) -} - -void CompositorResourceTracker::scheduleUpdateMailboxes(std::vector<CompositorResource *> resources) -{ -#if QT_CONFIG(opengl) - scoped_refptr<base::SingleThreadTaskRunner> gpuTaskRunner = gpu_task_runner(); - DCHECK(gpuTaskRunner); - thread_local bool currentThreadIsGpu = gpuTaskRunner->BelongsToCurrentThread(); - if (currentThreadIsGpu) - return updateMailboxes(std::move(resources)); - gpuTaskRunner->PostTask( - FROM_HERE, - base::BindOnce(&CompositorResourceTracker::updateMailboxes, - m_weakPtrFactory.GetWeakPtr(), - std::move(resources))); -#else - NOTREACHED(); -#endif // QT_CONFIG(OPENGL) -} - -void CompositorResourceTracker::updateMailboxes(std::vector<CompositorResource *> resources) -{ -#if QT_CONFIG(opengl) - for (CompositorResource *resource : resources) - resource->texture_id = consumeMailbox(resource->mailbox_holder); - - scoped_refptr<CompositorResourceFence> fence = CompositorResourceFence::create(); - - for (CompositorResource *resource : resources) - resource->texture_fence = fence; - - if ((m_pendingResourceUpdates -= resources.size()) == 0) - scheduleRunSubmitCallback(); -#else - NOTREACHED(); -#endif // QT_CONFIG(OPENGL) -} - -void CompositorResourceTracker::scheduleRunSubmitCallback() -{ - thread_local bool currentThreadIsUi = content::BrowserThread::CurrentlyOn(content::BrowserThread::UI); - if (currentThreadIsUi) - return runSubmitCallback(); - base::PostTaskWithTraits( - FROM_HERE, { content::BrowserThread::UI, base::TaskPriority::USER_VISIBLE }, - base::BindOnce(&CompositorResourceTracker::runSubmitCallback, - m_weakPtrFactory.GetWeakPtr())); -} - -void CompositorResourceTracker::runSubmitCallback() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - std::move(m_submitCallback).Run(); -} - -} // namespace QtWebEngineCore diff --git a/src/core/compositor/compositor_resource_tracker.h b/src/core/compositor/compositor_resource_tracker.h deleted file mode 100644 index 080891e5f..000000000 --- a/src/core/compositor/compositor_resource_tracker.h +++ /dev/null @@ -1,127 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef COMPOSITOR_RESOURCE_TRACKER_H -#define COMPOSITOR_RESOURCE_TRACKER_H - -#include "base/bind.h" -#include "base/callback.h" -#include "base/containers/flat_set.h" - -#include "compositor_resource.h" -#include "locked_ptr.h" - -#include <atomic> -#include <vector> - -namespace viz { -class CompositorFrame; -struct ReturnedResource; -} // namespace viz - -namespace gpu { -struct MailboxHolder; -} // namespace gpu - -namespace QtWebEngineCore { - -// Ensures resources are not used before they are ready. -// -// The life cycle of a frame's resources: -// -// Step 1. A new CompositorFrame is received and given to submitResources(). -// The frame's resources will extracted and initialized to a pending state. -// -// Step 2. Once the new resources are ready to be committed, -// CompositorResourceTracker will notify the client by running the callback -// given to submitResources(). -// -// Step 3. Once the client is ready to render, commitResources() should be -// called. This will commit all the pending resources, making them available -// via findResource(). -// -// Step 4. Once all the resources have been used (via findResource()), -// returnResources() may be called to return a list of all the resources which -// were *not* used since the last commitResources(). Go to step 1. -class CompositorResourceTracker final -{ -public: - CompositorResourceTracker(); - ~CompositorResourceTracker(); - - void submitResources(const viz::CompositorFrame &frame, base::OnceClosure callback); - void commitResources(); - std::vector<viz::ReturnedResource> returnResources(); - - // The returned pointer is invalidated by the next call to commitFrame() or - // returnResources(). It should therefore not be stored in data structures - // but used immediately. - // - // Do not ask for resources which do not exist. - const CompositorResource *findResource(CompositorResourceId id) const; - -private: - void updateBitmap(CompositorResource *resource); - - quint32 consumeMailbox(const gpu::MailboxHolder &mailboxHolder); - - bool scheduleUpdateMailbox(CompositorResource *resource); - void updateMailbox(CompositorResource *resource); - - void scheduleUpdateMailboxes(std::vector<CompositorResource *> resources); - void updateMailboxes(std::vector<CompositorResource *> resources); - - void scheduleRunSubmitCallback(); - void runSubmitCallback(); - - base::flat_set<CompositorResource> m_committedResources; - std::vector<CompositorResource> m_pendingResources; - std::vector<CompositorResource *> m_pendingImports; - base::OnceClosure m_submitCallback; - std::atomic<size_t> m_pendingResourceUpdates{0}; - quint32 m_committedFrameId = 0; - - base::LockedPtrFactory<CompositorResourceTracker> m_weakPtrFactory{this}; - - DISALLOW_COPY_AND_ASSIGN(CompositorResourceTracker); -}; - -} // namespace QtWebEngineCore - -#endif // !COMPOSITOR_RESOURCE_TRACKER_H diff --git a/src/core/compositor/content_gpu_client_qt.cpp b/src/core/compositor/content_gpu_client_qt.cpp index f934979a0..2c0f78548 100644 --- a/src/core/compositor/content_gpu_client_qt.cpp +++ b/src/core/compositor/content_gpu_client_qt.cpp @@ -38,22 +38,151 @@ ****************************************************************************/ #include "content_gpu_client_qt.h" - #include "web_engine_context.h" +#include "ui/gl/gl_share_group.h" +#include "ui/gl/gl_context.h" +#include "ui/gl/gl_implementation.h" +#include "ui/gl/gpu_timing.h" + +#if QT_CONFIG(opengl) +#include <QOpenGLContext> +#include <QOpenGLExtraFunctions> +#endif + +#include <QGuiApplication> +#include <qpa/qplatformnativeinterface.h> + +#if QT_CONFIG(opengl) +QT_BEGIN_NAMESPACE +Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context(); +QT_END_NAMESPACE +#endif namespace QtWebEngineCore { -ContentGpuClientQt::ContentGpuClientQt() +class QtShareGLContext : public gl::GLContext { -} +public: + QtShareGLContext(QOpenGLContext *qtContext) : gl::GLContext(0), m_handle(0) + { + QString platform = qApp->platformName().toLower(); + QPlatformNativeInterface *pni = QGuiApplication::platformNativeInterface(); + if (platform == QLatin1String("xcb") || platform == QLatin1String("offscreen")) { + if (gl::GetGLImplementation() == gl::kGLImplementationEGLGLES2) + m_handle = + pni->nativeResourceForContext(QByteArrayLiteral("eglcontext"), qtContext); + else + m_handle = + pni->nativeResourceForContext(QByteArrayLiteral("glxcontext"), qtContext); + } else if (platform == QLatin1String("cocoa")) + m_handle = pni->nativeResourceForContext(QByteArrayLiteral("cglcontextobj"), qtContext); + else if (platform == QLatin1String("qnx")) + m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglcontext"), qtContext); + else if (platform == QLatin1String("eglfs") || platform == QLatin1String("wayland") + || platform == QLatin1String("wayland-egl")) + m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglcontext"), qtContext); + else if (platform == QLatin1String("windows")) { + if (gl::GetGLImplementation() == gl::kGLImplementationEGLGLES2) + m_handle = + pni->nativeResourceForContext(QByteArrayLiteral("eglContext"), qtContext); + else + m_handle = pni->nativeResourceForContext(QByteArrayLiteral("renderingcontext"), + qtContext); + } else { + qFatal("%s platform not yet supported", platform.toLatin1().constData()); + // Add missing platforms once they work. + Q_UNREACHABLE(); + } + } + + void *GetHandle() override { return m_handle; } + unsigned int CheckStickyGraphicsResetStatusImpl() override + { +#if QT_CONFIG(opengl) + if (QOpenGLContext *context = qt_gl_global_share_context()) { + if (context->format().testOption(QSurfaceFormat::ResetNotification)) + return context->extraFunctions()->glGetGraphicsResetStatus(); + } +#endif + return 0 /*GL_NO_ERROR*/; + } + + // We don't care about the rest, this context shouldn't be used except for its handle. + bool Initialize(gl::GLSurface *, const gl::GLContextAttribs &) override + { + Q_UNREACHABLE(); + return false; + } + bool MakeCurrentImpl(gl::GLSurface *) override + { + Q_UNREACHABLE(); + return false; + } + void ReleaseCurrent(gl::GLSurface *) override + { + Q_UNREACHABLE(); + } + bool IsCurrent(gl::GLSurface *) override + { + Q_UNREACHABLE(); + return false; + } + scoped_refptr<gl::GPUTimingClient> CreateGPUTimingClient() override + { + return nullptr; + } + const gfx::ExtensionSet &GetExtensions() override + { + static const gfx::ExtensionSet s_emptySet; + return s_emptySet; + } + void ResetExtensions() override { } + +private: + void *m_handle; +}; -ContentGpuClientQt::~ContentGpuClientQt() +class ShareGroupQtQuick : public gl::GLShareGroup { +public: + gl::GLContext *GetContext() override { return m_shareContextQtQuick.get(); } + void AboutToAddFirstContext() override; + +private: + scoped_refptr<QtShareGLContext> m_shareContextQtQuick; +}; + +void ShareGroupQtQuick::AboutToAddFirstContext() +{ +#if QT_CONFIG(opengl) + // This currently has to be setup by ::main in all applications using QQuickWebEngineView + // with de legated rendering. + QOpenGLContext *shareContext = qt_gl_global_share_context(); + if (!shareContext) { + qFatal("QWebEngine: OpenGL resource sharing is not set up in QtQuick. Please make sure " + "to" + "call QtWebEngine::initialize() in your main() function before QCoreApplication " + "is " + "created."); + } + m_shareContextQtQuick = new QtShareGLContext(shareContext); +#endif } +ContentGpuClientQt::ContentGpuClientQt() { } + +ContentGpuClientQt::~ContentGpuClientQt() { } + gpu::SyncPointManager *ContentGpuClientQt::GetSyncPointManager() { return WebEngineContext::syncPointManager(); } +gl::GLShareGroup *ContentGpuClientQt::GetInProcessGpuShareGroup() +{ + if (!m_shareGroupQtQuick.get()) + m_shareGroupQtQuick = new ShareGroupQtQuick; + return m_shareGroupQtQuick.get(); +} + } // namespace diff --git a/src/core/compositor/content_gpu_client_qt.h b/src/core/compositor/content_gpu_client_qt.h index d7ad43881..5288c65bd 100644 --- a/src/core/compositor/content_gpu_client_qt.h +++ b/src/core/compositor/content_gpu_client_qt.h @@ -43,6 +43,8 @@ namespace QtWebEngineCore { +class ShareGroupQtQuick; + class ContentGpuClientQt : public content::ContentGpuClient { public: explicit ContentGpuClientQt(); @@ -50,6 +52,10 @@ public: // content::ContentGpuClient implementation. gpu::SyncPointManager *GetSyncPointManager() override; + gl::GLShareGroup *GetInProcessGpuShareGroup() override; + +private: + scoped_refptr<ShareGroupQtQuick> m_shareGroupQtQuick; }; } diff --git a/src/core/compositor/delegated_frame_node.cpp b/src/core/compositor/delegated_frame_node.cpp deleted file mode 100644 index 4d74937d9..000000000 --- a/src/core/compositor/delegated_frame_node.cpp +++ /dev/null @@ -1,1123 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// On Mac we need to reset this define in order to prevent definition -// of "check" macros etc. The "check" macro collides with a member function name in QtQuick. -// See AssertMacros.h in the Mac SDK. -#include <QtGlobal> // We need this for the Q_OS_MAC define. -#if defined(Q_OS_MAC) -#undef __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES -#define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0 -#endif - -#include "delegated_frame_node.h" - -#include "chromium_gpu_helper.h" -#include "stream_video_node.h" -#include "type_conversion.h" -#include "yuv_video_node.h" -#include "compositor_resource_tracker.h" - -#include "base/bind.h" -#include "cc/base/math_util.h" -#include "components/viz/common/quads/compositor_frame.h" -#include "components/viz/common/quads/debug_border_draw_quad.h" -#include "components/viz/common/quads/draw_quad.h" -#include "components/viz/common/quads/render_pass_draw_quad.h" -#include "components/viz/common/quads/solid_color_draw_quad.h" -#include "components/viz/common/quads/stream_video_draw_quad.h" -#include "components/viz/common/quads/texture_draw_quad.h" -#include "components/viz/common/quads/tile_draw_quad.h" -#include "components/viz/common/quads/yuv_video_draw_quad.h" -#include "components/viz/service/display/bsp_tree.h" -#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h" - -#ifndef QT_NO_OPENGL -# include <QOpenGLContext> -# include <QOpenGLFunctions> -# include <QSGFlatColorMaterial> -#endif -#include <QSGTexture> -#include <private/qsgadaptationlayer_p.h> - -#include <QSGImageNode> -#include <QSGRectangleNode> - -#if !defined(QT_NO_EGL) -#include <EGL/egl.h> -#include <EGL/eglext.h> -#endif - -#ifndef GL_TEXTURE_RECTANGLE -#define GL_TEXTURE_RECTANGLE 0x84F5 -#endif - -#ifndef GL_NEAREST -#define GL_NEAREST 0x2600 -#endif - -#ifndef GL_LINEAR -#define GL_LINEAR 0x2601 -#endif - -#ifndef GL_RGBA -#define GL_RGBA 0x1908 -#endif - -#ifndef GL_RGB -#define GL_RGB 0x1907 -#endif - -#ifndef GL_LINE_LOOP -#define GL_LINE_LOOP 0x0002 -#endif - -#ifndef QT_NO_OPENGL -QT_BEGIN_NAMESPACE -Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context(); -QT_END_NAMESPACE -#endif - -namespace QtWebEngineCore { -#ifndef QT_NO_OPENGL -class MailboxTexture : public QSGTexture, protected QOpenGLFunctions { -public: - MailboxTexture(const CompositorResource *resource, bool hasAlphaChannel, int target = -1); - ~MailboxTexture(); - // QSGTexture: - int textureId() const override { return m_textureId; } - QSize textureSize() const override { return m_textureSize; } - bool hasAlphaChannel() const override { return m_hasAlpha; } - bool hasMipmaps() const override { return false; } - void bind() override; - -private: - int m_textureId; - scoped_refptr<CompositorResourceFence> m_fence; - QSize m_textureSize; - bool m_hasAlpha; - GLenum m_target; -#if defined(USE_OZONE) - bool m_ownsTexture; -#endif -#ifdef Q_OS_QNX - EGLStreamData m_eglStreamData; -#endif - friend class DelegatedFrameNode; -}; -#endif // QT_NO_OPENGL - -class RectClipNode : public QSGClipNode -{ -public: - RectClipNode(const QRectF &); -private: - QSGGeometry m_geometry; -}; - -class DelegatedNodeTreeHandler -{ -public: - DelegatedNodeTreeHandler(QVector<QSGNode*> *sceneGraphNodes) - : m_sceneGraphNodes(sceneGraphNodes) - { - } - - virtual ~DelegatedNodeTreeHandler(){} - - virtual void setupRenderPassNode(QSGTexture *, const QRect &, const QRectF &, QSGNode *) = 0; - virtual void setupTextureContentNode(QSGTexture *, const QRect &, const QRectF &, - QSGImageNode::TextureCoordinatesTransformMode, - QSGNode *) = 0; - virtual void setupSolidColorNode(const QRect &, const QColor &, QSGNode *) = 0; - -#ifndef QT_NO_OPENGL - virtual void setupDebugBorderNode(QSGGeometry *, QSGFlatColorMaterial *, QSGNode *) = 0; - virtual void setupYUVVideoNode(QSGTexture *, QSGTexture *, QSGTexture *, QSGTexture *, - const QRectF &, const QRectF &, const QSizeF &, const QSizeF &, - gfx::ColorSpace, float, float, const QRectF &, - QSGNode *) = 0; -#ifdef GL_OES_EGL_image_external - virtual void setupStreamVideoNode(MailboxTexture *, const QRectF &, - const QMatrix4x4 &, QSGNode *) = 0; -#endif // GL_OES_EGL_image_external -#endif // QT_NO_OPENGL -protected: - QVector<QSGNode*> *m_sceneGraphNodes; -}; - -class DelegatedNodeTreeUpdater : public DelegatedNodeTreeHandler -{ -public: - DelegatedNodeTreeUpdater(QVector<QSGNode*> *sceneGraphNodes) - : DelegatedNodeTreeHandler(sceneGraphNodes) - , m_nodeIterator(sceneGraphNodes->begin()) - { - } - - void setupRenderPassNode(QSGTexture *layer, const QRect &rect, const QRectF &sourceRect, QSGNode *) override - { - Q_ASSERT(layer); - Q_ASSERT(m_nodeIterator != m_sceneGraphNodes->end()); - QSGImageNode *imageNode = static_cast<QSGImageNode*>(*m_nodeIterator++); - imageNode->setRect(rect); - imageNode->setSourceRect(sourceRect); - imageNode->setTexture(layer); - } - - void setupTextureContentNode(QSGTexture *texture, const QRect &rect, const QRectF &sourceRect, - QSGImageNode::TextureCoordinatesTransformMode texCoordTransForm, - QSGNode *) override - { - Q_ASSERT(m_nodeIterator != m_sceneGraphNodes->end()); - QSGImageNode *textureNode = static_cast<QSGImageNode*>(*m_nodeIterator++); - if (textureNode->texture() != texture) { - // Chromium sometimes uses textures that doesn't completely fit - // in which case the geometry needs to be recalculated even if - // rect and src-rect matches. - if (textureNode->texture()->textureSize() != texture->textureSize()) - textureNode->markDirty(QSGImageNode::DirtyGeometry); - textureNode->setTexture(texture); - } - if (textureNode->textureCoordinatesTransform() != texCoordTransForm) - textureNode->setTextureCoordinatesTransform(texCoordTransForm); - if (textureNode->rect() != rect) - textureNode->setRect(rect); - if (textureNode->sourceRect() != sourceRect) - textureNode->setSourceRect(sourceRect); - if (textureNode->filtering() != texture->filtering()) - textureNode->setFiltering(texture->filtering()); - } - void setupSolidColorNode(const QRect &rect, const QColor &color, QSGNode *) override - { - Q_ASSERT(m_nodeIterator != m_sceneGraphNodes->end()); - QSGRectangleNode *rectangleNode = static_cast<QSGRectangleNode*>(*m_nodeIterator++); - - if (rectangleNode->rect() != rect) - rectangleNode->setRect(rect); - if (rectangleNode->color() != color) - rectangleNode->setColor(color); - } -#ifndef QT_NO_OPENGL - void setupDebugBorderNode(QSGGeometry *geometry, QSGFlatColorMaterial *material, - QSGNode *) override - { - Q_ASSERT(m_nodeIterator != m_sceneGraphNodes->end()); - QSGGeometryNode *geometryNode = static_cast<QSGGeometryNode*>(*m_nodeIterator++); - - geometryNode->setGeometry(geometry); - geometryNode->setMaterial(material); - } - - void setupYUVVideoNode(QSGTexture *, QSGTexture *, QSGTexture *, QSGTexture *, - const QRectF &, const QRectF &, const QSizeF &, const QSizeF &, - gfx::ColorSpace, float, float, const QRectF &, - QSGNode *) override - { - Q_UNREACHABLE(); - } -#ifdef GL_OES_EGL_image_external - void setupStreamVideoNode(MailboxTexture *, const QRectF &, - const QMatrix4x4 &, QSGNode *) override - { - Q_UNREACHABLE(); - } -#endif // GL_OES_EGL_image_external -#endif // QT_NO_OPENGL - -private: - QVector<QSGNode*>::iterator m_nodeIterator; -}; - -class DelegatedNodeTreeCreator : public DelegatedNodeTreeHandler -{ -public: - DelegatedNodeTreeCreator(QVector<QSGNode*> *sceneGraphNodes, - RenderWidgetHostViewQtDelegate *apiDelegate) - : DelegatedNodeTreeHandler(sceneGraphNodes) - , m_apiDelegate(apiDelegate) - { - } - - void setupRenderPassNode(QSGTexture *layer, const QRect &rect, const QRectF &sourceRect, - QSGNode *layerChain) override - { - Q_ASSERT(layer); - QSGImageNode *imageNode = m_apiDelegate->createImageNode(); - imageNode->setRect(rect); - imageNode->setSourceRect(sourceRect); - imageNode->setTexture(layer); - - layerChain->appendChildNode(imageNode); - m_sceneGraphNodes->append(imageNode); - } - - void setupTextureContentNode(QSGTexture *texture, const QRect &rect, const QRectF &sourceRect, - QSGImageNode::TextureCoordinatesTransformMode texCoordTransForm, - QSGNode *layerChain) override - { - QSGImageNode *textureNode = m_apiDelegate->createImageNode(); - textureNode->setTextureCoordinatesTransform(texCoordTransForm); - textureNode->setRect(rect); - textureNode->setSourceRect(sourceRect); - textureNode->setTexture(texture); - textureNode->setFiltering(texture->filtering()); - - layerChain->appendChildNode(textureNode); - m_sceneGraphNodes->append(textureNode); - } - - void setupSolidColorNode(const QRect &rect, const QColor &color, - QSGNode *layerChain) override - { - QSGRectangleNode *rectangleNode = m_apiDelegate->createRectangleNode(); - rectangleNode->setRect(rect); - rectangleNode->setColor(color); - - layerChain->appendChildNode(rectangleNode); - m_sceneGraphNodes->append(rectangleNode); - } - -#ifndef QT_NO_OPENGL - void setupDebugBorderNode(QSGGeometry *geometry, QSGFlatColorMaterial *material, - QSGNode *layerChain) override - { - QSGGeometryNode *geometryNode = new QSGGeometryNode; - geometryNode->setFlags(QSGNode::OwnsGeometry | QSGNode::OwnsMaterial); - - geometryNode->setGeometry(geometry); - geometryNode->setMaterial(material); - - layerChain->appendChildNode(geometryNode); - m_sceneGraphNodes->append(geometryNode); - } - - void setupYUVVideoNode(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, - QSGTexture *aTexture, const QRectF &yaTexCoordRect, - const QRectF &uvTexCoordRect, const QSizeF &yaTexSize, - const QSizeF &uvTexSize, gfx::ColorSpace colorspace, - float rMul, float rOff, const QRectF &rect, - QSGNode *layerChain) override - { - YUVVideoNode *videoNode = new YUVVideoNode( - yTexture, - uTexture, - vTexture, - aTexture, - yaTexCoordRect, - uvTexCoordRect, - yaTexSize, - uvTexSize, - colorspace, - rMul, - rOff); - videoNode->setRect(rect); - - layerChain->appendChildNode(videoNode); - m_sceneGraphNodes->append(videoNode); - } -#ifdef GL_OES_EGL_image_external - void setupStreamVideoNode(MailboxTexture *texture, const QRectF &rect, - const QMatrix4x4 &textureMatrix, QSGNode *layerChain) override - { - StreamVideoNode *svideoNode = new StreamVideoNode(texture, false, ExternalTarget); - svideoNode->setRect(rect); - svideoNode->setTextureMatrix(textureMatrix); - layerChain->appendChildNode(svideoNode); - m_sceneGraphNodes->append(svideoNode); - } -#endif // GL_OES_EGL_image_external -#endif // QT_NO_OPENGL - -private: - RenderWidgetHostViewQtDelegate *m_apiDelegate; -}; - - -static inline QSharedPointer<QSGLayer> findRenderPassLayer(const int &id, const QVector<QPair<int, QSharedPointer<QSGLayer> > > &list) -{ - typedef QPair<int, QSharedPointer<QSGLayer> > Pair; - for (const Pair &pair : list) - if (pair.first == id) - return pair.second; - return QSharedPointer<QSGLayer>(); -} - -static QSGNode *buildRenderPassChain(QSGNode *chainParent) -{ - // Chromium already ordered the quads from back to front for us, however the - // Qt scene graph layers individual geometries in their own z-range and uses - // the depth buffer to visually stack nodes according to their item tree order. - - // This gets rid of the z component of all quads, once any x and y perspective - // transformation has been applied to vertices not on the z=0 plane. Qt will - // use an orthographic projection to render them. - QSGTransformNode *zCompressNode = new QSGTransformNode; - QMatrix4x4 zCompressMatrix; - zCompressMatrix.scale(1, 1, 0); - zCompressNode->setMatrix(zCompressMatrix); - chainParent->appendChildNode(zCompressNode); - return zCompressNode; -} - -static QSGNode *buildLayerChain(QSGNode *chainParent, const viz::SharedQuadState *layerState) -{ - QSGNode *layerChain = chainParent; - if (layerState->is_clipped) { - RectClipNode *clipNode = new RectClipNode(toQt(layerState->clip_rect)); - layerChain->appendChildNode(clipNode); - layerChain = clipNode; - } - if (!layerState->quad_to_target_transform.IsIdentity()) { - QSGTransformNode *transformNode = new QSGTransformNode; - QMatrix4x4 qMatrix; - convertToQt(layerState->quad_to_target_transform.matrix(), qMatrix); - transformNode->setMatrix(qMatrix); - layerChain->appendChildNode(transformNode); - layerChain = transformNode; - } - if (layerState->opacity < 1.0) { - QSGOpacityNode *opacityNode = new QSGOpacityNode; - opacityNode->setOpacity(layerState->opacity); - layerChain->appendChildNode(opacityNode); - layerChain = opacityNode; - } - return layerChain; -} - -#ifndef QT_NO_OPENGL -MailboxTexture::MailboxTexture(const CompositorResource *resource, bool hasAlphaChannel, int target) - : m_textureId(resource->texture_id) - , m_fence(resource->texture_fence) - , m_textureSize(toQt(resource->size)) - , m_hasAlpha(hasAlphaChannel) - , m_target(target >= 0 ? target : GL_TEXTURE_2D) -#if defined(USE_OZONE) - , m_ownsTexture(false) -#endif -{ - initializeOpenGLFunctions(); - - // Assume that resources without a size will be used with a full source rect. - // Setting a size of 1x1 will let any texture node compute a normalized source - // rect of (0, 0) to (1, 1) while an empty texture size would set (0, 0) on all corners. - if (m_textureSize.isEmpty()) - m_textureSize = QSize(1, 1); -} - -MailboxTexture::~MailboxTexture() -{ -#if defined(USE_OZONE) - // This is rare case, where context is not shared - // we created extra texture in current context, so - // delete it now - if (m_ownsTexture) { - QOpenGLContext *currentContext = QOpenGLContext::currentContext() ; - QOpenGLFunctions *funcs = currentContext->functions(); - GLuint id(m_textureId); - funcs->glDeleteTextures(1, &id); - } -#endif -} - -void MailboxTexture::bind() -{ - if (m_fence) - m_fence->wait(); - glBindTexture(m_target, m_textureId); -#ifdef Q_OS_QNX - if (m_target == GL_TEXTURE_EXTERNAL_OES) { - static bool resolved = false; - static PFNEGLSTREAMCONSUMERACQUIREKHRPROC eglStreamConsumerAcquire = 0; - - if (!resolved) { - QOpenGLContext *context = QOpenGLContext::currentContext(); - eglStreamConsumerAcquire = (PFNEGLSTREAMCONSUMERACQUIREKHRPROC)context->getProcAddress("eglStreamConsumerAcquireKHR"); - resolved = true; - } - if (eglStreamConsumerAcquire) - eglStreamConsumerAcquire(m_eglStreamData.egl_display, m_eglStreamData.egl_str_handle); - } -#endif -} -#endif // !QT_NO_OPENGL - -RectClipNode::RectClipNode(const QRectF &rect) - : m_geometry(QSGGeometry::defaultAttributes_Point2D(), 4) -{ - QSGGeometry::updateRectGeometry(&m_geometry, rect); - setGeometry(&m_geometry); - setClipRect(rect); - setIsRectangular(true); -} - -DelegatedFrameNode::DelegatedFrameNode() -#if defined(USE_OZONE) && !defined(QT_NO_OPENGL) - : m_contextShared(true) -#endif -{ - setFlag(UsePreprocess); -#if defined(USE_OZONE) && !defined(QT_NO_OPENGL) - QOpenGLContext *currentContext = QOpenGLContext::currentContext() ; - QOpenGLContext *sharedContext = qt_gl_global_share_context(); - if (currentContext && sharedContext && !QOpenGLContext::areSharing(currentContext, sharedContext)) { - static bool allowNotSharedContextWarningShown = true; - if (allowNotSharedContextWarningShown) { - allowNotSharedContextWarningShown = false; - qWarning("Context is not shared, textures will be copied between contexts."); - } - m_offsurface.reset(new QOffscreenSurface); - m_offsurface->create(); - m_contextShared = false; - } -#endif -} - -DelegatedFrameNode::~DelegatedFrameNode() -{ -} - -void DelegatedFrameNode::preprocess() -{ - // Then render any intermediate RenderPass in order. - typedef QPair<int, QSharedPointer<QSGLayer> > Pair; - for (const Pair &pair : qAsConst(m_sgObjects.renderPassLayers)) { - // The layer is non-live, request a one-time update here. - pair.second->scheduleUpdate(); - // Proceed with the actual update. - pair.second->updateTexture(); - } -} - -static bool areSharedQuadStatesEqual(const viz::SharedQuadState *layerState, - const viz::SharedQuadState *prevLayerState) -{ - if (layerState->sorting_context_id != 0 || prevLayerState->sorting_context_id != 0) - return false; - if (layerState->is_clipped != prevLayerState->is_clipped - || layerState->clip_rect != prevLayerState->clip_rect) - return false; - if (layerState->quad_to_target_transform != prevLayerState->quad_to_target_transform) - return false; - return qFuzzyCompare(layerState->opacity, prevLayerState->opacity); -} - -// Compares if the frame data that we got from the Chromium Compositor is -// *structurally* equivalent to the one of the previous frame. -// If it is, we will just reuse and update the old nodes where necessary. -static bool areRenderPassStructuresEqual(const viz::CompositorFrame *frameData, - const viz::CompositorFrame *previousFrameData) -{ - if (!previousFrameData) - return false; - - if (previousFrameData->render_pass_list.size() != frameData->render_pass_list.size()) - return false; - - for (unsigned i = 0; i < frameData->render_pass_list.size(); ++i) { - viz::RenderPass *newPass = frameData->render_pass_list.at(i).get(); - viz::RenderPass *prevPass = previousFrameData->render_pass_list.at(i).get(); - - if (newPass->id != prevPass->id) - return false; - - if (newPass->quad_list.size() != prevPass->quad_list.size()) - return false; - - viz::QuadList::ConstBackToFrontIterator it = newPass->quad_list.BackToFrontBegin(); - viz::QuadList::ConstBackToFrontIterator end = newPass->quad_list.BackToFrontEnd(); - viz::QuadList::ConstBackToFrontIterator prevIt = prevPass->quad_list.BackToFrontBegin(); - viz::QuadList::ConstBackToFrontIterator prevEnd = prevPass->quad_list.BackToFrontEnd(); - for (; it != end && prevIt != prevEnd; ++it, ++prevIt) { - const viz::DrawQuad *quad = *it; - const viz::DrawQuad *prevQuad = *prevIt; - if (quad->material != prevQuad->material) - return false; -#ifndef QT_NO_OPENGL - if (quad->material == viz::DrawQuad::Material::kYuvVideoContent) - return false; -#ifdef GL_OES_EGL_image_external - if (quad->material == viz::DrawQuad::Material::kStreamVideoContent) - return false; -#endif // GL_OES_EGL_image_external -#endif // QT_NO_OPENGL - if (!areSharedQuadStatesEqual(quad->shared_quad_state, prevQuad->shared_quad_state)) - return false; - if (quad->shared_quad_state->is_clipped && quad->visible_rect != prevQuad->visible_rect) { - gfx::Rect targetRect1 = - cc::MathUtil::MapEnclosingClippedRect(quad->shared_quad_state->quad_to_target_transform, quad->visible_rect); - gfx::Rect targetRect2 = - cc::MathUtil::MapEnclosingClippedRect(quad->shared_quad_state->quad_to_target_transform, prevQuad->visible_rect); - targetRect1.Intersect(quad->shared_quad_state->clip_rect); - targetRect2.Intersect(quad->shared_quad_state->clip_rect); - if (targetRect1.IsEmpty() != targetRect2.IsEmpty()) - return false; - } - } - } - return true; -} - -void DelegatedFrameNode::commit(const viz::CompositorFrame &pendingFrame, - const viz::CompositorFrame &committedFrame, - const CompositorResourceTracker *resourceTracker, - RenderWidgetHostViewQtDelegate *apiDelegate) -{ - const viz::CompositorFrame* frameData = &pendingFrame; - if (frameData->render_pass_list.empty()) - return; - - // DelegatedFrameNode is a transform node only for the purpose of - // countering the scale of devicePixel-scaled tiles when rendering them - // to the final surface. - QMatrix4x4 matrix; - const float devicePixelRatio = frameData->metadata.device_scale_factor; - matrix.scale(1 / devicePixelRatio, 1 / devicePixelRatio); - if (QSGTransformNode::matrix() != matrix) - setMatrix(matrix); - - QScopedPointer<DelegatedNodeTreeHandler> nodeHandler; - - const QSizeF viewportSizeInPt = apiDelegate->viewGeometry().size(); - const QSizeF viewportSizeF = viewportSizeInPt * devicePixelRatio; - const QSize viewportSize(std::ceil(viewportSizeF.width()), std::ceil(viewportSizeF.height())); - - // We first compare if the render passes from the previous frame data are structurally - // equivalent to the render passes in the current frame data. If they are, we are going - // to reuse the old nodes. Otherwise, we will delete the old nodes and build a new tree. - // - // Additionally, because we clip (i.e. don't build scene graph nodes for) quads outside - // of the visible area, we also have to rebuild the tree whenever the window is resized. - const bool buildNewTree = - !areRenderPassStructuresEqual(frameData, &committedFrame) || - m_sceneGraphNodes.empty() || - viewportSize != m_previousViewportSize; - - if (buildNewTree) { - // Keep the old objects in scope to hold a ref on layers, resources and textures - // that we can re-use. Destroy the remaining objects before returning. - qSwap(m_sgObjects, m_previousSGObjects); - // Discard the scene graph nodes from the previous frame. - while (QSGNode *oldChain = firstChild()) - delete oldChain; - m_sceneGraphNodes.clear(); - nodeHandler.reset(new DelegatedNodeTreeCreator(&m_sceneGraphNodes, apiDelegate)); - } else { - qSwap(m_sgObjects.bitmapTextures, m_previousSGObjects.bitmapTextures); - qSwap(m_sgObjects.mailboxTextures, m_previousSGObjects.mailboxTextures); - nodeHandler.reset(new DelegatedNodeTreeUpdater(&m_sceneGraphNodes)); - } - // The RenderPasses list is actually a tree where a parent RenderPass is connected - // to its dependencies through a RenderPassId reference in one or more RenderPassQuads. - // The list is already ordered with intermediate RenderPasses placed before their - // parent, with the last one in the list being the root RenderPass, the one - // that we displayed to the user. - // All RenderPasses except the last one are rendered to an FBO. - viz::RenderPass *rootRenderPass = frameData->render_pass_list.back().get(); - - gfx::Rect viewportRect(toGfx(viewportSize)); - for (unsigned i = 0; i < frameData->render_pass_list.size(); ++i) { - viz::RenderPass *pass = frameData->render_pass_list.at(i).get(); - - QSGNode *renderPassParent = 0; - gfx::Rect scissorRect; - if (pass != rootRenderPass) { - QSharedPointer<QSGLayer> rpLayer; - if (buildNewTree) { - rpLayer = findRenderPassLayer(pass->id, m_previousSGObjects.renderPassLayers); - if (!rpLayer) { - rpLayer = QSharedPointer<QSGLayer>(apiDelegate->createLayer()); - // Avoid any premature texture update since we need to wait - // for the GPU thread to produce the dependent resources first. - rpLayer->setLive(false); - } - QSharedPointer<QSGRootNode> rootNode(new QSGRootNode); - rpLayer->setItem(rootNode.data()); - m_sgObjects.renderPassLayers.append(QPair<int, - QSharedPointer<QSGLayer> >(pass->id, rpLayer)); - m_sgObjects.renderPassRootNodes.append(rootNode); - renderPassParent = rootNode.data(); - } else - rpLayer = findRenderPassLayer(pass->id, m_sgObjects.renderPassLayers); - - rpLayer->setRect(toQt(pass->output_rect)); - rpLayer->setSize(toQt(pass->output_rect.size())); - rpLayer->setFormat(pass->has_transparent_background ? GL_RGBA : GL_RGB); - rpLayer->setHasMipmaps(pass->generate_mipmap); - rpLayer->setMirrorVertical(true); - scissorRect = pass->output_rect; - } else { - renderPassParent = this; - scissorRect = viewportRect; - scissorRect += rootRenderPass->output_rect.OffsetFromOrigin(); - } - - if (scissorRect.IsEmpty()) { - holdResources(pass, resourceTracker); - continue; - } - - QSGNode *renderPassChain = nullptr; - if (buildNewTree) - renderPassChain = buildRenderPassChain(renderPassParent); - - base::circular_deque<std::unique_ptr<viz::DrawPolygon>> polygonQueue; - int nextPolygonId = 0; - int currentSortingContextId = 0; - const viz::SharedQuadState *currentLayerState = nullptr; - QSGNode *currentLayerChain = nullptr; - const auto quadListBegin = pass->quad_list.BackToFrontBegin(); - const auto quadListEnd = pass->quad_list.BackToFrontEnd(); - for (auto it = quadListBegin; it != quadListEnd; ++it) { - const viz::DrawQuad *quad = *it; - const viz::SharedQuadState *quadState = quad->shared_quad_state; - - gfx::Rect targetRect = - cc::MathUtil::MapEnclosingClippedRect(quadState->quad_to_target_transform, - quad->visible_rect); - if (quadState->is_clipped) - targetRect.Intersect(quadState->clip_rect); - targetRect.Intersect(scissorRect); - if (targetRect.IsEmpty()) { - holdResources(quad, resourceTracker); - continue; - } - - if (quadState->sorting_context_id != currentSortingContextId) { - flushPolygons(&polygonQueue, renderPassChain, - nodeHandler.data(), resourceTracker, apiDelegate); - currentSortingContextId = quadState->sorting_context_id; - } - - if (currentSortingContextId != 0) { - std::unique_ptr<viz::DrawPolygon> polygon( - new viz::DrawPolygon( - quad, - gfx::RectF(quad->visible_rect), - quadState->quad_to_target_transform, - nextPolygonId++)); - if (polygon->points().size() > 2u) - polygonQueue.push_back(std::move(polygon)); - continue; - } - - if (renderPassChain && currentLayerState != quadState) { - currentLayerState = quadState; - currentLayerChain = buildLayerChain(renderPassChain, quadState); - } - - handleQuad(quad, currentLayerChain, - nodeHandler.data(), resourceTracker, apiDelegate); - } - flushPolygons(&polygonQueue, renderPassChain, - nodeHandler.data(), resourceTracker, apiDelegate); - } - - copyMailboxTextures(); - - m_previousViewportSize = viewportSize; - m_previousSGObjects = SGObjects(); -} - -void DelegatedFrameNode::flushPolygons( - base::circular_deque<std::unique_ptr<viz::DrawPolygon>> *polygonQueue, - QSGNode *renderPassChain, - DelegatedNodeTreeHandler *nodeHandler, - const CompositorResourceTracker *resourceTracker, - RenderWidgetHostViewQtDelegate *apiDelegate) -{ - if (polygonQueue->empty()) - return; - - const auto actionHandler = [&](viz::DrawPolygon *polygon) { - const viz::DrawQuad *quad = polygon->original_ref(); - const viz::SharedQuadState *quadState = quad->shared_quad_state; - - QSGNode *currentLayerChain = nullptr; - if (renderPassChain) - currentLayerChain = buildLayerChain(renderPassChain, quad->shared_quad_state); - - gfx::Transform inverseTransform; - bool invertible = quadState->quad_to_target_transform.GetInverse(&inverseTransform); - DCHECK(invertible); - polygon->TransformToLayerSpace(inverseTransform); - - handlePolygon(polygon, currentLayerChain, - nodeHandler, resourceTracker, apiDelegate); - }; - - viz::BspTree(polygonQueue).TraverseWithActionHandler(&actionHandler); -} - -void DelegatedFrameNode::handlePolygon( - const viz::DrawPolygon *polygon, - QSGNode *currentLayerChain, - DelegatedNodeTreeHandler *nodeHandler, - const CompositorResourceTracker *resourceTracker, - RenderWidgetHostViewQtDelegate *apiDelegate) -{ - const viz::DrawQuad *quad = polygon->original_ref(); - - if (!polygon->is_split()) { - handleQuad(quad, currentLayerChain, - nodeHandler, resourceTracker, apiDelegate); - } else { - std::vector<gfx::QuadF> clipRegionList; - polygon->ToQuads2D(&clipRegionList); - for (const auto & clipRegion : clipRegionList) - handleClippedQuad(quad, clipRegion, currentLayerChain, - nodeHandler, resourceTracker, apiDelegate); - } -} - -void DelegatedFrameNode::handleClippedQuad( - const viz::DrawQuad *quad, - const gfx::QuadF &clipRegion, - QSGNode *currentLayerChain, - DelegatedNodeTreeHandler *nodeHandler, - const CompositorResourceTracker *resourceTracker, - RenderWidgetHostViewQtDelegate *apiDelegate) -{ - if (currentLayerChain) { - auto clipGeometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 4); - auto clipGeometryVertices = clipGeometry->vertexDataAsPoint2D(); - clipGeometryVertices[0].set(clipRegion.p1().x(), clipRegion.p1().y()); - clipGeometryVertices[1].set(clipRegion.p2().x(), clipRegion.p2().y()); - clipGeometryVertices[2].set(clipRegion.p4().x(), clipRegion.p4().y()); - clipGeometryVertices[3].set(clipRegion.p3().x(), clipRegion.p3().y()); - auto clipNode = new QSGClipNode; - clipNode->setGeometry(clipGeometry); - clipNode->setIsRectangular(false); - clipNode->setFlag(QSGNode::OwnsGeometry); - currentLayerChain->appendChildNode(clipNode); - currentLayerChain = clipNode; - } - handleQuad(quad, currentLayerChain, - nodeHandler, resourceTracker, apiDelegate); -} - -void DelegatedFrameNode::handleQuad( - const viz::DrawQuad *quad, - QSGNode *currentLayerChain, - DelegatedNodeTreeHandler *nodeHandler, - const CompositorResourceTracker *resourceTracker, - RenderWidgetHostViewQtDelegate *apiDelegate) -{ - switch (quad->material) { - case viz::DrawQuad::Material::kRenderPass: { - const viz::RenderPassDrawQuad *renderPassQuad = viz::RenderPassDrawQuad::MaterialCast(quad); - if (!renderPassQuad->mask_texture_size.IsEmpty()) { - const CompositorResource *resource = findAndHoldResource(renderPassQuad->mask_resource_id(), resourceTracker); - Q_UNUSED(resource); // FIXME: QTBUG-67652 - } - QSGLayer *layer = - findRenderPassLayer(renderPassQuad->render_pass_id, m_sgObjects.renderPassLayers).data(); - - if (layer) - nodeHandler->setupRenderPassNode(layer, toQt(quad->rect), toQt(renderPassQuad->tex_coord_rect), currentLayerChain); - - break; - } - case viz::DrawQuad::Material::kTextureContent: { - const viz::TextureDrawQuad *tquad = viz::TextureDrawQuad::MaterialCast(quad); - const CompositorResource *resource = findAndHoldResource(tquad->resource_id(), resourceTracker); - QSGTexture *texture = - initAndHoldTexture(resource, quad->ShouldDrawWithBlending(true), apiDelegate); - QSizeF textureSize; - if (texture) - textureSize = texture->textureSize(); - gfx::RectF uv_rect = - gfx::ScaleRect(gfx::BoundingRect(tquad->uv_top_left, tquad->uv_bottom_right), - textureSize.width(), textureSize.height()); - - nodeHandler->setupTextureContentNode( - texture, toQt(quad->rect), toQt(uv_rect), - tquad->y_flipped ? QSGImageNode::MirrorVertically : QSGImageNode::NoTransform, - currentLayerChain); - break; - } - case viz::DrawQuad::Material::kSolidColor: { - const viz::SolidColorDrawQuad *scquad = viz::SolidColorDrawQuad::MaterialCast(quad); - // Qt only supports MSAA and this flag shouldn't be needed. - // If we ever want to use QSGRectangleNode::setAntialiasing for this we should - // try to see if we can do something similar for tile quads first. - Q_UNUSED(scquad->force_anti_aliasing_off); - nodeHandler->setupSolidColorNode(toQt(quad->rect), toQt(scquad->color), currentLayerChain); - break; -#ifndef QT_NO_OPENGL - } - case viz::DrawQuad::Material::kDebugBorder: { - const viz::DebugBorderDrawQuad *dbquad = viz::DebugBorderDrawQuad::MaterialCast(quad); - - QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 4); - geometry->setDrawingMode(GL_LINE_LOOP); - geometry->setLineWidth(dbquad->width); - // QSGGeometry::updateRectGeometry would actually set the - // corners in the following order: - // top-left, bottom-left, top-right, bottom-right, leading to a nice criss cross, - // instead of having a closed loop. - const gfx::Rect &r(dbquad->rect); - geometry->vertexDataAsPoint2D()[0].set(r.x(), r.y()); - geometry->vertexDataAsPoint2D()[1].set(r.x() + r.width(), r.y()); - geometry->vertexDataAsPoint2D()[2].set(r.x() + r.width(), r.y() + r.height()); - geometry->vertexDataAsPoint2D()[3].set(r.x(), r.y() + r.height()); - - QSGFlatColorMaterial *material = new QSGFlatColorMaterial; - material->setColor(toQt(dbquad->color)); - - nodeHandler->setupDebugBorderNode(geometry, material, currentLayerChain); - break; -#endif - } - case viz::DrawQuad::Material::kTiledContent: { - const viz::TileDrawQuad *tquad = viz::TileDrawQuad::MaterialCast(quad); - const CompositorResource *resource = findAndHoldResource(tquad->resource_id(), resourceTracker); - nodeHandler->setupTextureContentNode( - initAndHoldTexture(resource, quad->ShouldDrawWithBlending(true), apiDelegate), - toQt(quad->rect), toQt(tquad->tex_coord_rect), - QSGImageNode::NoTransform, currentLayerChain); - break; -#ifndef QT_NO_OPENGL - } - case viz::DrawQuad::Material::kYuvVideoContent: { - const viz::YUVVideoDrawQuad *vquad = viz::YUVVideoDrawQuad::MaterialCast(quad); - const CompositorResource *yResource = - findAndHoldResource(vquad->y_plane_resource_id(), resourceTracker); - const CompositorResource *uResource = - findAndHoldResource(vquad->u_plane_resource_id(), resourceTracker); - const CompositorResource *vResource = - findAndHoldResource(vquad->v_plane_resource_id(), resourceTracker); - const CompositorResource *aResource = nullptr; - // This currently requires --enable-vp8-alpha-playback and - // needs a video with alpha data to be triggered. - if (vquad->a_plane_resource_id()) - aResource = findAndHoldResource(vquad->a_plane_resource_id(), resourceTracker); - - nodeHandler->setupYUVVideoNode( - initAndHoldTexture(yResource, quad->ShouldDrawWithBlending(true)), - initAndHoldTexture(uResource, quad->ShouldDrawWithBlending(true)), - initAndHoldTexture(vResource, quad->ShouldDrawWithBlending(true)), - aResource ? initAndHoldTexture(aResource, quad->ShouldDrawWithBlending(true)) : 0, - toQt(vquad->ya_tex_coord_rect), toQt(vquad->uv_tex_coord_rect), - toQt(vquad->ya_tex_size), toQt(vquad->uv_tex_size), vquad->video_color_space, - vquad->resource_multiplier, vquad->resource_offset, toQt(quad->rect), - currentLayerChain); - break; -#ifdef GL_OES_EGL_image_external - } - case viz::DrawQuad::Material::kStreamVideoContent: { - const viz::StreamVideoDrawQuad *squad = viz::StreamVideoDrawQuad::MaterialCast(quad); - const CompositorResource *resource = findAndHoldResource(squad->resource_id(), resourceTracker); - MailboxTexture *texture = static_cast<MailboxTexture *>( - initAndHoldTexture(resource, quad->ShouldDrawWithBlending(true), apiDelegate, GL_TEXTURE_EXTERNAL_OES)); - - QMatrix4x4 qMatrix; -// convertToQt(squad->matrix.matrix(), qMatrix); - nodeHandler->setupStreamVideoNode(texture, toQt(squad->rect), qMatrix, currentLayerChain); - break; -#endif // GL_OES_EGL_image_external -#endif // QT_NO_OPENGL - } - case viz::DrawQuad::Material::kSurfaceContent: - Q_UNREACHABLE(); - default: - qWarning("Unimplemented quad material: %d", (int)quad->material); - } -} - -const CompositorResource *DelegatedFrameNode::findAndHoldResource(unsigned resourceId, const CompositorResourceTracker *resourceTracker) -{ - return resourceTracker->findResource(resourceId); -} - -void DelegatedFrameNode::holdResources(const viz::DrawQuad *quad, const CompositorResourceTracker *resourceTracker) -{ - for (auto resource : quad->resources) - findAndHoldResource(resource, resourceTracker); -} - -void DelegatedFrameNode::holdResources(const viz::RenderPass *pass, const CompositorResourceTracker *resourceTracker) -{ - for (const auto &quad : pass->quad_list) - holdResources(quad, resourceTracker); -} - -template<class Container, class Key> -inline auto &findTexture(Container &map, Container &previousMap, const Key &key) -{ - auto &value = map[key]; - if (value) - return value; - value = previousMap[key]; - return value; -} - -QSGTexture *DelegatedFrameNode::initAndHoldTexture(const CompositorResource *resource, bool hasAlphaChannel, RenderWidgetHostViewQtDelegate *apiDelegate, int target) -{ - QSGTexture::Filtering filtering; - - if (resource->filter == GL_NEAREST) - filtering = QSGTexture::Nearest; - else if (resource->filter == GL_LINEAR) - filtering = QSGTexture::Linear; - else { - // Depends on qtdeclarative fix, see QTBUG-71322 -#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 1) - filtering = QSGTexture::Linear; -#else - filtering = QSGTexture::Nearest; -#endif - } - - if (resource->is_software) { - QSharedPointer<QSGTexture> &texture = - findTexture(m_sgObjects.bitmapTextures, m_previousSGObjects.bitmapTextures, resource->id); - if (texture) - return texture.data(); - texture = createBitmapTexture(resource, hasAlphaChannel, apiDelegate); - texture->setFiltering(filtering); - return texture.data(); - } else { -#if QT_CONFIG(opengl) - QSharedPointer<MailboxTexture> &texture = - findTexture(m_sgObjects.mailboxTextures, m_previousSGObjects.mailboxTextures, resource->id); - if (texture) - return texture.data(); - texture = createMailboxTexture(resource, hasAlphaChannel, target); - texture->setFiltering(filtering); - return texture.data(); -#else - Q_UNREACHABLE(); - return nullptr; -#endif - } -} - -QSharedPointer<QSGTexture> DelegatedFrameNode::createBitmapTexture(const CompositorResource *resource, bool hasAlphaChannel, RenderWidgetHostViewQtDelegate *apiDelegate) -{ - Q_ASSERT(apiDelegate); - viz::SharedBitmap *sharedBitmap = resource->bitmap.get(); - gfx::Size size = resource->size; - - // QSG interprets QImage::hasAlphaChannel meaning that a node should enable blending - // to draw it but Chromium keeps this information in the quads. - // The input format is currently always Format_ARGB32_Premultiplied, so assume that all - // alpha bytes are 0xff if quads aren't requesting blending and avoid the conversion - // from Format_ARGB32_Premultiplied to Format_RGB32 just to get hasAlphaChannel to - // return false. - QImage::Format format = hasAlphaChannel ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32; - QImage image = sharedBitmap - ? QImage(sharedBitmap->pixels(), size.width(), size.height(), format) - : QImage(size.width(), size.height(), format); - return QSharedPointer<QSGTexture>(apiDelegate->createTextureFromImage(image.copy())); -} - -QSharedPointer<MailboxTexture> DelegatedFrameNode::createMailboxTexture(const CompositorResource *resource, bool hasAlphaChannel, int target) -{ -#ifndef QT_NO_OPENGL - return QSharedPointer<MailboxTexture>::create(resource, hasAlphaChannel, target); -#else - Q_UNREACHABLE(); -#endif -} - -void DelegatedFrameNode::copyMailboxTextures() -{ -#if !defined(QT_NO_OPENGL) && defined(USE_OZONE) - // Workaround when context is not shared QTBUG-48969 - // Make slow copy between two contexts. - if (!m_contextShared) { - QOpenGLContext *currentContext = QOpenGLContext::currentContext() ; - QOpenGLContext *sharedContext = qt_gl_global_share_context(); - - QSurface *surface = currentContext->surface(); - Q_ASSERT(m_offsurface); - sharedContext->makeCurrent(m_offsurface.data()); - QOpenGLFunctions *funcs = sharedContext->functions(); - - GLuint fbo = 0; - funcs->glGenFramebuffers(1, &fbo); - - for (const QSharedPointer<MailboxTexture> &mailboxTexture : qAsConst(m_sgObjects.mailboxTextures)) { - if (mailboxTexture->m_ownsTexture) - continue; - - // Read texture into QImage from shared context. - // Switch to shared context. - sharedContext->makeCurrent(m_offsurface.data()); - funcs = sharedContext->functions(); - QImage img(mailboxTexture->textureSize(), QImage::Format_RGBA8888_Premultiplied); - funcs->glBindFramebuffer(GL_FRAMEBUFFER, fbo); - mailboxTexture->m_fence->wait(); - funcs->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mailboxTexture->m_textureId, 0); - GLenum status = funcs->glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - qWarning("fbo error, skipping slow copy..."); - continue; - } - funcs->glReadPixels(0, 0, mailboxTexture->textureSize().width(), mailboxTexture->textureSize().height(), - GL_RGBA, GL_UNSIGNED_BYTE, img.bits()); - - // Restore current context. - // Create texture from QImage in current context. - currentContext->makeCurrent(surface); - GLuint texture = 0; - funcs = currentContext->functions(); - funcs->glGenTextures(1, &texture); - funcs->glBindTexture(GL_TEXTURE_2D, texture); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mailboxTexture->textureSize().width(), mailboxTexture->textureSize().height(), 0, - GL_RGBA, GL_UNSIGNED_BYTE, img.bits()); - mailboxTexture->m_textureId = texture; - mailboxTexture->m_ownsTexture = true; - } - // Cleanup allocated resources - sharedContext->makeCurrent(m_offsurface.data()); - funcs = sharedContext->functions(); - funcs->glBindFramebuffer(GL_FRAMEBUFFER, 0); - funcs->glDeleteFramebuffers(1, &fbo); - currentContext->makeCurrent(surface); - } -#endif -} - -} // namespace QtWebEngineCore diff --git a/src/core/compositor/delegated_frame_node.h b/src/core/compositor/delegated_frame_node.h deleted file mode 100644 index 34e4ba029..000000000 --- a/src/core/compositor/delegated_frame_node.h +++ /dev/null @@ -1,133 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef DELEGATED_FRAME_NODE_H -#define DELEGATED_FRAME_NODE_H - -#include "base/containers/circular_deque.h" -#include "components/viz/common/quads/compositor_frame.h" -#include "components/viz/common/quads/render_pass.h" - -#include <QtCore/QSharedPointer> -#include <QtGui/QOffscreenSurface> -#include <QtQuick/QSGTransformNode> - -#include "chromium_gpu_helper.h" -#include "render_widget_host_view_qt_delegate.h" - -QT_BEGIN_NAMESPACE -class QSGLayer; -QT_END_NAMESPACE - -namespace gfx { -class QuadF; -} - -namespace viz { -class DelegatedFrameData; -class DrawQuad; -class DrawPolygon; -} - -namespace QtWebEngineCore { - -class CompositorResource; -class CompositorResourceTracker; -class DelegatedNodeTreeHandler; -class MailboxTexture; - -class DelegatedFrameNode : public QSGTransformNode { -public: - DelegatedFrameNode(); - ~DelegatedFrameNode(); - void preprocess() override; - void commit(const viz::CompositorFrame &pendingFrame, const viz::CompositorFrame &committedFrame, const CompositorResourceTracker *resourceTracker, RenderWidgetHostViewQtDelegate *apiDelegate); - -private: - void flushPolygons(base::circular_deque<std::unique_ptr<viz::DrawPolygon> > *polygonQueue, - QSGNode *renderPassChain, - DelegatedNodeTreeHandler *nodeHandler, - const CompositorResourceTracker *resourceTracker, - RenderWidgetHostViewQtDelegate *apiDelegate); - void handlePolygon( - const viz::DrawPolygon *polygon, - QSGNode *currentLayerChain, - DelegatedNodeTreeHandler *nodeHandler, - const CompositorResourceTracker *resourceTracker, - RenderWidgetHostViewQtDelegate *apiDelegate); - void handleClippedQuad( - const viz::DrawQuad *quad, - const gfx::QuadF &clipRegion, - QSGNode *currentLayerChain, - DelegatedNodeTreeHandler *nodeHandler, - const CompositorResourceTracker *resourceTracker, - RenderWidgetHostViewQtDelegate *apiDelegate); - void handleQuad( - const viz::DrawQuad *quad, - QSGNode *currentLayerChain, - DelegatedNodeTreeHandler *nodeHandler, - const CompositorResourceTracker *resourceTracker, - RenderWidgetHostViewQtDelegate *apiDelegate); - - const CompositorResource *findAndHoldResource(unsigned resourceId, const CompositorResourceTracker *resourceTracker); - void holdResources(const viz::DrawQuad *quad, const CompositorResourceTracker *resourceTracker); - void holdResources(const viz::RenderPass *pass, const CompositorResourceTracker *resourceTracker); - QSGTexture *initAndHoldTexture(const CompositorResource *resource, bool hasAlphaChannel, RenderWidgetHostViewQtDelegate *apiDelegate = 0, int target = -1); - QSharedPointer<QSGTexture> createBitmapTexture(const CompositorResource *resource, bool hasAlphaChannel, RenderWidgetHostViewQtDelegate *apiDelegate); - QSharedPointer<MailboxTexture> createMailboxTexture(const CompositorResource *resource, bool hasAlphaChannel, int target); - - void copyMailboxTextures(); - - struct SGObjects { - QVector<QPair<int, QSharedPointer<QSGLayer> > > renderPassLayers; - QVector<QSharedPointer<QSGRootNode> > renderPassRootNodes; - QHash<unsigned, QSharedPointer<QSGTexture> > bitmapTextures; - QHash<unsigned, QSharedPointer<MailboxTexture> > mailboxTextures; - } m_sgObjects, m_previousSGObjects; - QVector<QSGNode*> m_sceneGraphNodes; -#if defined(USE_OZONE) - bool m_contextShared; - QScopedPointer<QOffscreenSurface> m_offsurface; -#endif - QSize m_previousViewportSize; -}; - -} // namespace QtWebEngineCore - -#endif // DELEGATED_FRAME_NODE_H diff --git a/src/core/compositor/display_gl_output_surface.cpp b/src/core/compositor/display_gl_output_surface.cpp index 0077af112..370eb07e6 100644 --- a/src/core/compositor/display_gl_output_surface.cpp +++ b/src/core/compositor/display_gl_output_surface.cpp @@ -39,8 +39,6 @@ #include "display_gl_output_surface.h" -#include "chromium_gpu_helper.h" - #include "base/threading/thread_task_runner_handle.h" #include "components/viz/service/display/display.h" #include "components/viz/service/display/output_surface_frame.h" @@ -49,7 +47,7 @@ #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/texture_base.h" #include "gpu/ipc/in_process_command_buffer.h" -#include "ui/gl/color_space_utils.h" +#include "ui/gfx/buffer_format_util.h" namespace QtWebEngineCore { @@ -113,12 +111,13 @@ void DisplayGLOutputSurface::DiscardBackbuffer() void DisplayGLOutputSurface::Reshape(const gfx::Size &sizeInPixels, float devicePixelRatio, const gfx::ColorSpace &colorSpace, - bool hasAlpha, + gfx::BufferFormat format, bool /*useStencil*/) { + bool hasAlpha = gfx::AlphaBitsForBufferFormat(format) > 0; m_currentShape = Shape{sizeInPixels, devicePixelRatio, colorSpace, hasAlpha}; m_gl->ResizeCHROMIUM(sizeInPixels.width(), sizeInPixels.height(), devicePixelRatio, - gl::ColorSpaceUtils::GetGLColorSpace(colorSpace), hasAlpha); + colorSpace.AsGLColorSpace(), hasAlpha); } std::unique_ptr<DisplayGLOutputSurface::Buffer> DisplayGLOutputSurface::makeBuffer(const Shape &shape) @@ -211,6 +210,7 @@ void DisplayGLOutputSurface::swapBuffersOnGpuThread(unsigned int id, std::unique QMutexLocker locker(&m_mutex); m_middleBuffer->serviceId = id; m_middleBuffer->fence = CompositorResourceFence::create(std::move(fence)); + m_readyToUpdate = true; } m_sink->scheduleUpdate(); @@ -249,13 +249,6 @@ unsigned DisplayGLOutputSurface::GetOverlayTextureId() const return 0; } -// Only used if IsDisplayedAsOverlayPlane was true (called from -// viz::DirectRender::DrawFrame). -gfx::BufferFormat DisplayGLOutputSurface::GetOverlayBufferFormat() const -{ - return gfx::BufferFormat(); -} - // Called by viz::GLRenderer but always false in all implementations except for // android_webview::ParentOutputSurface. bool DisplayGLOutputSurface::HasExternalStencilTest() const @@ -273,7 +266,7 @@ void DisplayGLOutputSurface::ApplyExternalStencil() // glCopyTexSubImage2D on our framebuffer. uint32_t DisplayGLOutputSurface::GetFramebufferCopyTextureFormat() { - return GL_RGBA; + return m_currentShape.hasAlpha ? GL_RGBA : GL_RGB; } // Called from viz::DirectRenderer::DrawFrame, only used for overlays. @@ -283,6 +276,16 @@ unsigned DisplayGLOutputSurface::UpdateGpuFence() return 0; } +scoped_refptr<gpu::GpuTaskSchedulerHelper> DisplayGLOutputSurface::GetGpuTaskSchedulerHelper() +{ + return m_vizContextProvider->GetGpuTaskSchedulerHelper(); +} + +gpu::MemoryTracker *DisplayGLOutputSurface::GetMemoryTracker() +{ + return m_vizContextProvider->GetMemoryTracker(); +} + void DisplayGLOutputSurface::SetUpdateVSyncParametersCallback(viz::UpdateVSyncParametersCallback callback) { m_vizContextProvider->SetUpdateVSyncParametersCallback(std::move(callback)); diff --git a/src/core/compositor/display_gl_output_surface.h b/src/core/compositor/display_gl_output_surface.h index 67d987263..d2e203b4e 100644 --- a/src/core/compositor/display_gl_output_surface.h +++ b/src/core/compositor/display_gl_output_surface.h @@ -72,11 +72,10 @@ public: void SetDrawRectangle(const gfx::Rect &drawRect) override; bool IsDisplayedAsOverlayPlane() const override; unsigned GetOverlayTextureId() const override; - gfx::BufferFormat GetOverlayBufferFormat() const override; void Reshape(const gfx::Size &size, float devicePixelRatio, const gfx::ColorSpace &colorSpace, - bool hasAlpha, + gfx::BufferFormat format, bool useStencil) override; bool HasExternalStencilTest() const override; void ApplyExternalStencil() override; @@ -86,6 +85,8 @@ public: void SetUpdateVSyncParametersCallback(viz::UpdateVSyncParametersCallback callback) override; void SetDisplayTransformHint(gfx::OverlayTransform transform) override; gfx::OverlayTransform GetDisplayTransform() override; + scoped_refptr<gpu::GpuTaskSchedulerHelper> GetGpuTaskSchedulerHelper() override; + gpu::MemoryTracker *GetMemoryTracker() override; // Overridden from DisplayProducer. QSGNode *updatePaintNode(QSGNode *oldNode, RenderWidgetHostViewQtDelegate *delegate) override; @@ -140,6 +141,7 @@ private: std::unique_ptr<Buffer> m_backBuffer; std::unique_ptr<Buffer> m_middleBuffer; std::unique_ptr<Buffer> m_frontBuffer; + bool m_readyToUpdate = false; scoped_refptr<base::SingleThreadTaskRunner> m_taskRunner; scoped_refptr<viz::VizProcessContextProvider> m_vizContextProvider; }; diff --git a/src/core/compositor/display_gl_output_surface_qsg.cpp b/src/core/compositor/display_gl_output_surface_qsg.cpp index 2f7b3de84..0e9fff6e3 100644 --- a/src/core/compositor/display_gl_output_surface_qsg.cpp +++ b/src/core/compositor/display_gl_output_surface_qsg.cpp @@ -88,12 +88,13 @@ QSGNode *DisplayGLOutputSurface::updatePaintNode(QSGNode *oldNode, RenderWidgetH { { QMutexLocker locker(&m_mutex); - if (m_middleBuffer && m_middleBuffer->serviceId) { + if (m_readyToUpdate) { std::swap(m_middleBuffer, m_frontBuffer); m_taskRunner->PostTask( FROM_HERE, base::BindOnce(&DisplayGLOutputSurface::swapBuffersOnVizThread, base::Unretained(this))); m_taskRunner.reset(); + m_readyToUpdate = false; } } diff --git a/src/core/compositor/display_overrides.cpp b/src/core/compositor/display_overrides.cpp index 5d999ab92..89bf8ad2f 100644 --- a/src/core/compositor/display_overrides.cpp +++ b/src/core/compositor/display_overrides.cpp @@ -42,12 +42,17 @@ #include "components/viz/service/display_embedder/output_surface_provider_impl.h" #include "gpu/ipc/in_process_command_buffer.h" +#include <qtgui-config.h> std::unique_ptr<viz::OutputSurface> viz::OutputSurfaceProviderImpl::CreateGLOutputSurface( scoped_refptr<VizProcessContextProvider> context_provider) { +#if QT_CONFIG(opengl) return std::make_unique<QtWebEngineCore::DisplayGLOutputSurface>(std::move(context_provider)); +#else + return nullptr; +#endif // QT_CONFIG(opengl) } std::unique_ptr<viz::OutputSurface> @@ -71,7 +76,10 @@ void gpu::InProcessCommandBuffer::GetTextureQt( void gpu::InProcessCommandBuffer::GetTextureQtOnGpuThread( unsigned int client_id, GetTextureCallback callback) { - MakeCurrent(); + if (!MakeCurrent()) { + LOG(ERROR) << "MakeCurrent failed for GetTextureQt"; + return; + } gpu::TextureBase *texture = decoder_->GetTextureBase(client_id); std::move(callback).Run(texture ? texture->service_id() : 0, gl::GLFence::Create()); } diff --git a/src/core/compositor/display_software_output_surface.cpp b/src/core/compositor/display_software_output_surface.cpp index 5d3c7a6f6..ba99799f0 100644 --- a/src/core/compositor/display_software_output_surface.cpp +++ b/src/core/compositor/display_software_output_surface.cpp @@ -137,7 +137,9 @@ QSGNode *DisplaySoftwareOutputSurface::Device::updatePaintNode( skPixmap.rowBytes(), imageFormat(skPixmap.colorType())); if (m_image.size() == image.size()) { QRect damageRect = toQt(damage_rect_); - QPainter(&m_image).drawImage(damageRect, image, damageRect); + QPainter painter(&m_image); + painter.setCompositionMode(QPainter::CompositionMode_Source); + painter.drawImage(damageRect, image, damageRect); } else { m_image = image; m_image.detach(); diff --git a/src/core/compositor/stream_video_node.cpp b/src/core/compositor/stream_video_node.cpp deleted file mode 100644 index fb9501f24..000000000 --- a/src/core/compositor/stream_video_node.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "stream_video_node.h" - -#include <QtQuick/qsgtexture.h> - -namespace QtWebEngineCore { - -class StreamVideoMaterialShader : public QSGMaterialShader -{ -public: - StreamVideoMaterialShader(TextureTarget target) : m_target(target) { } - virtual void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; - - char const *const *attributeNames() const override { - static const char *names[] = { - "a_position", - "a_texCoord", - 0 - }; - return names; - } - -protected: - const char *vertexShader() const override { - // Keep in sync with cc::VertexShaderVideoTransform - static const char *shader = - "attribute highp vec4 a_position;\n" - "attribute mediump vec2 a_texCoord;\n" - "uniform highp mat4 matrix;\n" - "uniform highp mat4 texMatrix;\n" - "varying mediump vec2 v_texCoord;\n" - "void main() {\n" - " gl_Position = matrix * a_position;\n" - " v_texCoord = vec4(texMatrix * vec4(a_texCoord.x, 1.0 - a_texCoord.y, 0.0, 1.0)).xy;\n" - "}"; - return shader; - } - - const char *fragmentShader() const override { - // Keep in sync with cc::FragmentShaderRGBATexAlpha - static const char *shaderExternal = - "#extension GL_OES_EGL_image_external : require\n" - "varying mediump vec2 v_texCoord;\n" - "uniform samplerExternalOES s_texture;\n" - "uniform lowp float alpha;\n" - "void main() {\n" - " lowp vec4 texColor = texture2D(s_texture, v_texCoord);\n" - " gl_FragColor = texColor * alpha;\n" - "}"; - static const char *shader2DRect = - "#extension GL_ARB_texture_rectangle : require\n" - "varying mediump vec2 v_texCoord;\n" - "uniform sampler2DRect s_texture;\n" - "uniform lowp float alpha;\n" - "void main() {\n" - " lowp vec4 texColor = texture2DRect(s_texture, v_texCoord);\n" - " gl_FragColor = texColor * alpha;\n" - "}"; - if (m_target == ExternalTarget) - return shaderExternal; - else - return shader2DRect; - } - - virtual void initialize() override { - m_id_matrix = program()->uniformLocation("matrix"); - m_id_sTexture = program()->uniformLocation("s_texture"); - m_id_texMatrix = program()->uniformLocation("texMatrix"); - m_id_opacity = program()->uniformLocation("alpha"); - } - - int m_id_matrix; - int m_id_texMatrix; - int m_id_sTexture; - int m_id_opacity; - TextureTarget m_target; -}; - -void StreamVideoMaterialShader::updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) -{ - Q_UNUSED(oldMaterial); - - StreamVideoMaterial *mat = static_cast<StreamVideoMaterial *>(newMaterial); - program()->setUniformValue(m_id_sTexture, 0); - - mat->m_texture->bind(); - - if (state.isOpacityDirty()) - program()->setUniformValue(m_id_opacity, state.opacity()); - - if (state.isMatrixDirty()) - program()->setUniformValue(m_id_matrix, state.combinedMatrix()); - - program()->setUniformValue(m_id_texMatrix, mat->m_texMatrix); -} - -StreamVideoMaterial::StreamVideoMaterial(QSGTexture *texture, TextureTarget target) - : m_texture(texture) - , m_target(target) -{ -} - -QSGMaterialShader *StreamVideoMaterial::createShader() const -{ - return new StreamVideoMaterialShader(m_target); -} - -StreamVideoNode::StreamVideoNode(QSGTexture *texture, bool flip, TextureTarget target) - : m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4) - , m_flip(flip) -{ - setGeometry(&m_geometry); - setFlag(QSGNode::OwnsMaterial); - m_material = new StreamVideoMaterial(texture, target); - setMaterial(m_material); -} - -void StreamVideoNode::setRect(const QRectF &rect) -{ - if (m_flip) - QSGGeometry::updateTexturedRectGeometry(geometry(), rect, QRectF(0, 1, 1, -1)); - else - QSGGeometry::updateTexturedRectGeometry(geometry(), rect, QRectF(0, 0, 1, 1)); -} - -void StreamVideoNode::setTextureMatrix(const QMatrix4x4 &matrix) -{ - m_material->m_texMatrix = matrix; -} - -} // namespace diff --git a/src/core/compositor/yuv_video_node.cpp b/src/core/compositor/yuv_video_node.cpp deleted file mode 100644 index 4a436d952..000000000 --- a/src/core/compositor/yuv_video_node.cpp +++ /dev/null @@ -1,352 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// Based on cc/output/gl_renderer.cc and cc/output/shader.cc: -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE.Chromium file. - -#include "yuv_video_node.h" - -#include <QtGui/qopenglcontext.h> -#include <QtGui/qopenglfunctions.h> -#include <QtQuick/qsgtexture.h> - -#include "ui/gfx/color_space.h" -#include "ui/gfx/color_transform.h" - -namespace QtWebEngineCore { - -class YUVVideoMaterialShader : public QSGMaterialShader -{ -public: - YUVVideoMaterialShader(const gfx::ColorSpace &colorSpace) - { - static const char *shaderHead = - "varying mediump vec2 v_yaTexCoord;\n" - "varying mediump vec2 v_uvTexCoord;\n" - "uniform sampler2D y_texture;\n" - "uniform sampler2D u_texture;\n" - "uniform sampler2D v_texture;\n" - "uniform mediump float alpha;\n" - "uniform mediump vec4 ya_clamp_rect;\n" - "uniform mediump vec4 uv_clamp_rect;\n"; - static const char *shader = - "void main() {\n" - " mediump vec2 ya_clamped =\n" - " max(ya_clamp_rect.xy, min(ya_clamp_rect.zw, v_yaTexCoord));\n" - " mediump float y_raw = texture2D(y_texture, ya_clamped).x;\n" - " mediump vec2 uv_clamped =\n" - " max(uv_clamp_rect.xy, min(uv_clamp_rect.zw, v_uvTexCoord));\n" - " mediump float u_unsigned = texture2D(u_texture, uv_clamped).x;\n" - " mediump float v_unsigned = texture2D(v_texture, uv_clamped).x;\n" - " mediump vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned);\n" - " mediump vec3 rgb = DoColorConversion(yuv);\n" - " gl_FragColor = vec4(rgb, 1.0) * alpha;\n" - "}"; - // Invalid or unspecified color spaces should be treated as REC709. - gfx::ColorSpace src = colorSpace.IsValid() ? colorSpace : gfx::ColorSpace::CreateREC709(); - gfx::ColorSpace dst = gfx::ColorSpace::CreateSRGB(); - std::unique_ptr<gfx::ColorTransform> transform = - gfx::ColorTransform::NewColorTransform(src, dst, gfx::ColorTransform::Intent::INTENT_PERCEPTUAL); - - QByteArray header(shaderHead); - if (QOpenGLContext::currentContext()->isOpenGLES()) - header = QByteArray("precision mediump float;\n") + header; - - m_csShader = QByteArray::fromStdString(transform->GetShaderSource()); - m_fragmentShader = header + m_csShader + QByteArray(shader); - } - void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; - - char const *const *attributeNames() const override { - static const char *names[] = { - "a_position", - "a_texCoord", - 0 - }; - return names; - } - -protected: - const char *vertexShader() const override { - // Keep in sync with logic in VertexShader in components/viz/service/display/shader.cc - const char *shader = - "attribute highp vec4 a_position;\n" - "attribute mediump vec2 a_texCoord;\n" - "uniform highp mat4 matrix;\n" - "varying mediump vec2 v_yaTexCoord;\n" - "varying mediump vec2 v_uvTexCoord;\n" - "uniform mediump vec2 yaTexScale;\n" - "uniform mediump vec2 yaTexOffset;\n" - "uniform mediump vec2 uvTexScale;\n" - "uniform mediump vec2 uvTexOffset;\n" - "void main() {\n" - " gl_Position = matrix * a_position;\n" - " v_yaTexCoord = a_texCoord * yaTexScale + yaTexOffset;\n" - " v_uvTexCoord = a_texCoord * uvTexScale + uvTexOffset;\n" - "}"; - return shader; - } - - const char *fragmentShader() const override { - return m_fragmentShader.constData(); - } - - void initialize() override { - m_id_matrix = program()->uniformLocation("matrix"); - m_id_yaTexScale = program()->uniformLocation("yaTexScale"); - m_id_uvTexScale = program()->uniformLocation("uvTexScale"); - m_id_yaTexOffset = program()->uniformLocation("yaTexOffset"); - m_id_uvTexOffset = program()->uniformLocation("uvTexOffset"); - m_id_yaClampRect = program()->uniformLocation("ya_clamp_rect"); - m_id_uvClampRect = program()->uniformLocation("uv_clamp_rect"); - m_id_yTexture = program()->uniformLocation("y_texture"); - m_id_uTexture = program()->uniformLocation("u_texture"); - m_id_vTexture = program()->uniformLocation("v_texture"); - m_id_yuvMatrix = program()->uniformLocation("yuv_matrix"); - m_id_yuvAdjust = program()->uniformLocation("yuv_adj"); - m_id_opacity = program()->uniformLocation("alpha"); - } - - int m_id_matrix; - int m_id_yaTexScale; - int m_id_uvTexScale; - int m_id_yaTexOffset; - int m_id_uvTexOffset; - int m_id_yaClampRect; - int m_id_uvClampRect; - int m_id_yTexture; - int m_id_uTexture; - int m_id_vTexture; - int m_id_yuvMatrix; - int m_id_yuvAdjust; - int m_id_opacity; - QByteArray m_csShader; - QByteArray m_fragmentShader; -}; - -class YUVAVideoMaterialShader : public YUVVideoMaterialShader -{ -public: - YUVAVideoMaterialShader(const gfx::ColorSpace &colorSpace) : YUVVideoMaterialShader(colorSpace) - { - static const char *shaderHead = - "varying mediump vec2 v_yaTexCoord;\n" - "varying mediump vec2 v_uvTexCoord;\n" - "uniform sampler2D y_texture;\n" - "uniform sampler2D u_texture;\n" - "uniform sampler2D v_texture;\n" - "uniform sampler2D a_texture;\n" - "uniform mediump float alpha;\n" - "uniform mediump vec4 ya_clamp_rect;\n" - "uniform mediump vec4 uv_clamp_rect;\n"; - static const char *shader = - "void main() {\n" - " mediump vec2 ya_clamped =\n" - " max(ya_clamp_rect.xy, min(ya_clamp_rect.zw, v_yaTexCoord));\n" - " mediump float y_raw = texture2D(y_texture, ya_clamped).x;\n" - " mediump vec2 uv_clamped =\n" - " max(uv_clamp_rect.xy, min(uv_clamp_rect.zw, v_uvTexCoord));\n" - " mediump float u_unsigned = texture2D(u_texture, uv_clamped).x;\n" - " mediump float v_unsigned = texture2D(v_texture, uv_clamped).x;\n" - " mediump float a_raw = texture2D(a_texture, ya_clamped).x;\n" - " mediump vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned);\n" - " mediump vec3 rgb = DoColorConversion(yuv);\n" - " gl_FragColor = vec4(rgb, 1.0) * (alpha * a_raw);\n" - "}"; - QByteArray header(shaderHead); - if (QOpenGLContext::currentContext()->isOpenGLES()) - header = QByteArray("precision mediump float;\n") + header; - m_fragmentShader = header + m_csShader + QByteArray(shader); - } - void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; - -protected: - void initialize() override { - // YUVVideoMaterialShader has a subset of the uniforms. - YUVVideoMaterialShader::initialize(); - m_id_aTexture = program()->uniformLocation("a_texture"); - } - - int m_id_aTexture; -}; - -void YUVVideoMaterialShader::updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) -{ - Q_UNUSED(oldMaterial); - - // Keep logic in sync with logic in GLRenderer::DrawYUVVideoQuad: - - YUVVideoMaterial *mat = static_cast<YUVVideoMaterial *>(newMaterial); - program()->setUniformValue(m_id_yTexture, 0); - program()->setUniformValue(m_id_uTexture, 1); - program()->setUniformValue(m_id_vTexture, 2); - - QOpenGLFunctions glFuncs(QOpenGLContext::currentContext()); - - glFuncs.glActiveTexture(GL_TEXTURE1); - mat->m_uTexture->bind(); - glFuncs.glActiveTexture(GL_TEXTURE2); - mat->m_vTexture->bind(); - glFuncs.glActiveTexture(GL_TEXTURE0); // Finish with 0 as default texture unit - mat->m_yTexture->bind(); - - const QSizeF yaSizeScale(1.0f / mat->m_yaTexSize.width(), 1.0f / mat->m_yaTexSize.height()); - const QSizeF uvSizeScale(1.0f / mat->m_uvTexSize.width(), 1.0f / mat->m_uvTexSize.height()); - - const QPointF yaTexOffset(mat->m_yaTexCoordRect.left() * yaSizeScale.width(), mat->m_yaTexCoordRect.top() * yaSizeScale.height()); - const QPointF uvTexOffset(mat->m_uvTexCoordRect.left() * uvSizeScale.width(), mat->m_uvTexCoordRect.top() * uvSizeScale.height()); - const QSizeF yaTexScale(mat->m_yaTexCoordRect.width() * yaSizeScale.width(), mat->m_yaTexCoordRect.height() * yaSizeScale.height()); - const QSizeF uvTexScale(mat->m_uvTexCoordRect.width() * uvSizeScale.width(), mat->m_uvTexCoordRect.height() * uvSizeScale.height()); - program()->setUniformValue(m_id_yaTexOffset, yaTexOffset); - program()->setUniformValue(m_id_uvTexOffset, uvTexOffset); - program()->setUniformValue(m_id_yaTexScale, yaTexScale); - program()->setUniformValue(m_id_uvTexScale, uvTexScale); - QRectF yaClampRect(yaTexOffset, yaTexScale); - QRectF uvClampRect(uvTexOffset, uvTexScale); - yaClampRect = yaClampRect.marginsRemoved(QMarginsF(yaSizeScale.width() * 0.5f, yaSizeScale.height() * 0.5f, - yaSizeScale.width() * 0.5f, yaSizeScale.height() * 0.5f)); - uvClampRect = uvClampRect.marginsRemoved(QMarginsF(uvSizeScale.width() * 0.5f, uvSizeScale.height() * 0.5f, - uvSizeScale.width() * 0.5f, uvSizeScale.height() * 0.5f)); - - const QVector4D yaClampV(yaClampRect.left(), yaClampRect.top(), yaClampRect.right(), yaClampRect.bottom()); - const QVector4D uvClampV(uvClampRect.left(), uvClampRect.top(), uvClampRect.right(), uvClampRect.bottom()); - program()->setUniformValue(m_id_yaClampRect, yaClampV); - program()->setUniformValue(m_id_uvClampRect, uvClampV); - - if (state.isOpacityDirty()) - program()->setUniformValue(m_id_opacity, state.opacity()); - - if (state.isMatrixDirty()) - program()->setUniformValue(m_id_matrix, state.combinedMatrix()); -} - -void YUVAVideoMaterialShader::updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) -{ - YUVVideoMaterialShader::updateState(state, newMaterial, oldMaterial); - - YUVAVideoMaterial *mat = static_cast<YUVAVideoMaterial *>(newMaterial); - program()->setUniformValue(m_id_aTexture, 3); - - QOpenGLFunctions glFuncs(QOpenGLContext::currentContext()); - - glFuncs.glActiveTexture(GL_TEXTURE3); - mat->m_aTexture->bind(); - - // Reset the default texture unit. - glFuncs.glActiveTexture(GL_TEXTURE0); -} - - -YUVVideoMaterial::YUVVideoMaterial(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, - const QRectF &yaTexCoordRect, const QRectF &uvTexCoordRect, const QSizeF &yaTexSize, const QSizeF &uvTexSize, - const gfx::ColorSpace &colorspace, - float rMul, float rOff) - : m_yTexture(yTexture) - , m_uTexture(uTexture) - , m_vTexture(vTexture) - , m_yaTexCoordRect(yaTexCoordRect) - , m_uvTexCoordRect(uvTexCoordRect) - , m_yaTexSize(yaTexSize) - , m_uvTexSize(uvTexSize) - , m_colorSpace(colorspace) - , m_resourceMultiplier(rMul) - , m_resourceOffset(rOff) -{ -} - -QSGMaterialShader *YUVVideoMaterial::createShader() const -{ - return new YUVVideoMaterialShader(m_colorSpace); -} - -int YUVVideoMaterial::compare(const QSGMaterial *other) const -{ - const YUVVideoMaterial *m = static_cast<const YUVVideoMaterial *>(other); - if (int diff = m_yTexture->textureId() - m->m_yTexture->textureId()) - return diff; - if (int diff = m_uTexture->textureId() - m->m_uTexture->textureId()) - return diff; - return m_vTexture->textureId() - m->m_vTexture->textureId(); -} - -YUVAVideoMaterial::YUVAVideoMaterial(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, QSGTexture *aTexture, - const QRectF &yaTexCoordRect, const QRectF &uvTexCoordRect, const QSizeF &yaTexSize, const QSizeF &uvTexSize, - const gfx::ColorSpace &colorspace, - float rMul, float rOff) - : YUVVideoMaterial(yTexture, uTexture, vTexture, yaTexCoordRect, uvTexCoordRect, yaTexSize, uvTexSize, colorspace, rMul, rOff) - , m_aTexture(aTexture) -{ - setFlag(Blending, aTexture); -} - -QSGMaterialShader *YUVAVideoMaterial::createShader() const -{ - return new YUVAVideoMaterialShader(m_colorSpace); -} - -int YUVAVideoMaterial::compare(const QSGMaterial *other) const -{ - if (int diff = YUVVideoMaterial::compare(other)) - return diff; - const YUVAVideoMaterial *m = static_cast<const YUVAVideoMaterial *>(other); - return (m_aTexture ? m_aTexture->textureId() : 0) - (m->m_aTexture ? m->m_aTexture->textureId() : 0); -} - -YUVVideoNode::YUVVideoNode(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, QSGTexture *aTexture, - const QRectF &yaTexCoordRect, const QRectF &uvTexCoordRect, const QSizeF &yaTexSize, const QSizeF &uvTexSize, - const gfx::ColorSpace &colorspace, float rMul, float rOff) - : m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4) -{ - setGeometry(&m_geometry); - setFlag(QSGNode::OwnsMaterial); - if (aTexture) - m_material = new YUVAVideoMaterial(yTexture, uTexture, vTexture, aTexture, yaTexCoordRect, uvTexCoordRect, yaTexSize, uvTexSize, colorspace, rMul, rOff); - else - m_material = new YUVVideoMaterial(yTexture, uTexture, vTexture, yaTexCoordRect, uvTexCoordRect, yaTexSize, uvTexSize, colorspace, rMul, rOff); - setMaterial(m_material); -} - -void YUVVideoNode::setRect(const QRectF &rect) -{ - QSGGeometry::updateTexturedRectGeometry(geometry(), rect, QRectF(0, 0, 1, 1)); -} - -} // namespace diff --git a/src/core/compositor/yuv_video_node.h b/src/core/compositor/yuv_video_node.h deleted file mode 100644 index dca8fa5e2..000000000 --- a/src/core/compositor/yuv_video_node.h +++ /dev/null @@ -1,117 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef YUV_VIDEO_NODE_H -#define YUV_VIDEO_NODE_H - -#include <QtQuick/qsgmaterial.h> -#include <QtQuick/qsgnode.h> - -#include "ui/gfx/color_space.h" - -QT_FORWARD_DECLARE_CLASS(QSGTexture) - -namespace QtWebEngineCore { - -// These classes duplicate, QtQuick style, the logic of GLRenderer::DrawYUVVideoQuad. -// Their behavior should stay as close as possible to GLRenderer. - -class YUVVideoMaterial : public QSGMaterial -{ -public: - YUVVideoMaterial(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, - const QRectF &yaTexCoordRect, const QRectF &uvTexCoordRect, const QSizeF &yaTexSize, const QSizeF &uvTexSize, - const gfx::ColorSpace &colorspace, float rMul, float rOff); - - QSGMaterialType *type() const override - { - static QSGMaterialType theType; - return &theType; - } - - QSGMaterialShader *createShader() const override; - int compare(const QSGMaterial *other) const override; - - QSGTexture *m_yTexture; - QSGTexture *m_uTexture; - QSGTexture *m_vTexture; - QRectF m_yaTexCoordRect; - QRectF m_uvTexCoordRect; - QSizeF m_yaTexSize; - QSizeF m_uvTexSize; - gfx::ColorSpace m_colorSpace; - float m_resourceMultiplier; - float m_resourceOffset; -}; - -class YUVAVideoMaterial : public YUVVideoMaterial -{ -public: - YUVAVideoMaterial(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, QSGTexture *aTexture, - const QRectF &yaTexCoordRect, const QRectF &uvTexCoordRect, const QSizeF &yaTexSize, const QSizeF &uvTexSize, - const gfx::ColorSpace &colorspace, float rMul, float rOff); - - QSGMaterialType *type() const override - { - static QSGMaterialType theType; - return &theType; - } - - QSGMaterialShader *createShader() const override; - int compare(const QSGMaterial *other) const override; - - QSGTexture *m_aTexture; -}; - -class YUVVideoNode : public QSGGeometryNode -{ -public: - YUVVideoNode(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, QSGTexture *aTexture, - const QRectF &yaTexCoordRect, const QRectF &uvTexCoordRect, const QSizeF &yaTexSize, const QSizeF &uvTexSize, - const gfx::ColorSpace &colorspace, float rMul, float rOff); - void setRect(const QRectF &rect); - -private: - QSGGeometry m_geometry; - YUVVideoMaterial *m_material; -}; - -} // namespace - -#endif // YUV_VIDEO_NODE_H diff --git a/src/core/config/common.pri b/src/core/config/common.pri new file mode 100644 index 000000000..fc46d55ce --- /dev/null +++ b/src/core/config/common.pri @@ -0,0 +1,49 @@ +qtConfig(webengine-printing-and-pdf) { + gn_args += enable_basic_printing=true enable_print_preview=true + gn_args += enable_pdf=true +} else { + gn_args += enable_basic_printing=false enable_print_preview=false + gn_args += enable_pdf=false +} + +qtConfig(webengine-pepper-plugins) { + gn_args += enable_plugins=true +} else { + gn_args += enable_plugins=false +} + +qtConfig(webengine-spellchecker) { + gn_args += enable_spellcheck=true +} else { + gn_args += enable_spellcheck=false +} + +qtConfig(webengine-webrtc) { + gn_args += enable_webrtc=true +} else { + gn_args += enable_webrtc=false +} + +qtConfig(webengine-proprietary-codecs) { + gn_args += proprietary_codecs=true ffmpeg_branding=\"Chrome\" + qtConfig(webengine-webrtc) { + gn_args += rtc_use_h264=true + } +} else { + gn_args += proprietary_codecs=false +} + +qtConfig(webengine-extensions) { + gn_args += enable_extensions=true +} else { + gn_args += enable_extensions=false +} + +qtConfig(webengine-kerberos) { + gn_args += use_kerberos=true +} else { + gn_args += use_kerberos=false +} + +!qtConfig(webengine-nodejs10): gn_args += use_rollup=false +gn_args += enable_ipc_logging=false diff --git a/src/core/config/linux.pri b/src/core/config/linux.pri new file mode 100644 index 000000000..33dd28b42 --- /dev/null +++ b/src/core/config/linux.pri @@ -0,0 +1,46 @@ +include(common.pri) + +qtConfig(webengine-embedded-build) { + gn_args += is_desktop_linux=false +} + +!host_build{ + + + + qtConfig(webengine-pulseaudio) { + gn_args += use_pulseaudio=true + } else { + gn_args += use_pulseaudio=false + } + + qtConfig(webengine-alsa) { + gn_args += use_alsa=true + } else { + gn_args += use_alsa=false + } + + !packagesExist(libpci): gn_args += use_libpci=false + + qtConfig(webengine-ozone-x11) { + gn_args += ozone_platform_x11=true + gn_args += use_xkbcommon=true + packagesExist(xscrnsaver): gn_args += use_xscrnsaver=true + qtConfig(webengine-webrtc): gn_args += rtc_use_x11=true + } else { + gn_args += use_xkbcommon=false + } + + qtConfig(webengine-webrtc): qtConfig(webengine-webrtc-pipewire): gn_args += rtc_use_pipewire=true + + qtConfig(webengine-system-libevent): gn_args += use_system_libevent=true + qtConfig(webengine-system-libwebp): gn_args += use_system_libwebp=true + qtConfig(webengine-system-libxml2): gn_args += use_system_libxml=true use_system_libxslt=true + qtConfig(webengine-system-opus): gn_args += use_system_opus=true + qtConfig(webengine-system-snappy): gn_args += use_system_snappy=true + qtConfig(webengine-system-libvpx): gn_args += use_system_libvpx=true + qtConfig(webengine-system-icu): gn_args += use_system_icu=true icu_use_data_file=false + qtConfig(webengine-system-ffmpeg): gn_args += use_system_ffmpeg=true + qtConfig(webengine-system-re2): gn_args += use_system_re2=true + qtConfig(webengine-system-lcms2): gn_args += use_system_lcms2=true +} diff --git a/src/core/config/mac_osx.pri b/src/core/config/mac_osx.pri new file mode 100644 index 000000000..9543daf90 --- /dev/null +++ b/src/core/config/mac_osx.pri @@ -0,0 +1,8 @@ +include(common.pri) + +qtConfig(build-qtwebengine-core):qtConfig(webengine-spellchecker) { + qtConfig(webengine-native-spellchecker): gn_args += use_browser_spellchecker=true + else: gn_args += use_browser_spellchecker=false +} else { + gn_args += use_browser_spellchecker=false +} diff --git a/src/core/config/windows.pri b/src/core/config/windows.pri new file mode 100644 index 000000000..9543daf90 --- /dev/null +++ b/src/core/config/windows.pri @@ -0,0 +1,8 @@ +include(common.pri) + +qtConfig(build-qtwebengine-core):qtConfig(webengine-spellchecker) { + qtConfig(webengine-native-spellchecker): gn_args += use_browser_spellchecker=true + else: gn_args += use_browser_spellchecker=false +} else { + gn_args += use_browser_spellchecker=false +} diff --git a/src/core/configure.json b/src/core/configure.json index d7f5a92f1..9e39ae59a 100644 --- a/src/core/configure.json +++ b/src/core/configure.json @@ -6,7 +6,7 @@ "gui-private", "printsupport" ], - "condition": "features.build-qtwebengine-core && features.webengine-core-support", + "condition": "module.gui && features.build-qtwebengine-core && features.webengine-core-support", "testDir": "../../config.tests", "commandline": { "options": { @@ -25,8 +25,8 @@ "webengine-native-spellchecker": "boolean", "webengine-extensions": "boolean", "webengine-webrtc": "boolean", + "webengine-webrtc-pipewire": "boolean", "webengine-geolocation": "boolean", - "webengine-v8-snapshot": "boolean", "webengine-webchannel": "boolean", "webengine-kerberos": "boolean", "alsa": { "type": "boolean", "name": "webengine-alsa" }, @@ -68,6 +68,12 @@ "sources": [ { "type": "pkgConfig", "args": "libpulse >= 0.9.10 libpulse-mainloop-glib" } ] + }, + "webengine-gio": { + "label": "gio", + "sources": [ + { "type": "pkgConfig", "args": "gio-2.0" } + ] } }, "tests" : { @@ -85,26 +91,12 @@ "webengine-embedded-build": { "label": "embedded build", "type": "detectEmbedded" - }, - "webengine-sanitizer": { - "label" : "sanitizer support", - "type": "isSanitizerSupported" - }, - "webengine-arm-thumb" : { - "label": "thumb instruction set", - "type": "hasThumbFlag" - }, - "webengine-noexecstack" : { - "label": "linker supports -z noexecstack", - "type": "linkerSupportsFlag", - "flag": "-z,noexecstack" } }, "features": { "webengine-embedded-build": { "label": "Embedded build", "purpose": "Enables the embedded build configuration.", - "section": "WebEngine", "condition": "config.unix", "autoDetect": "tests.webengine-embedded-build", "output": [ "privateFeature" ] @@ -114,14 +106,8 @@ "condition": "config.unix && libs.webengine-alsa", "output": [ "privateFeature" ] }, - "webengine-v8-snapshot": { - "label" : "Use v8 snapshot", - "purpose": "Enables the v8 snapshot, for fast v8 context creation", - "output": [ "privateFeature" ] - }, "webengine-v8-snapshot-support": { "label" : "Building v8 snapshot supported", - "autoDetect": "features.webengine-v8-snapshot", "condition": "!config.unix || !features.cross_compile || arch.arm64 || tests.webengine-host-compiler", "output": [ "privateFeature" ] }, @@ -139,14 +125,12 @@ "webengine-pepper-plugins": { "label": "Pepper Plugins", "purpose": "Enables use of Pepper Flash plugins.", - "section": "WebEngine", "autoDetect": "!features.webengine-embedded-build", "output": [ "privateFeature" ] }, "webengine-printing-and-pdf": { "label": "Printing and PDF", "purpose": "Provides printing and output to PDF.", - "section": "WebEngine", "condition": "module.printsupport && features.printer", "autoDetect": "!features.webengine-embedded-build", "output": [ "privateFeature" ] @@ -161,7 +145,6 @@ "webengine-proprietary-codecs": { "label": "Proprietary Codecs", "purpose": "Enables the use of proprietary codecs such as h.264/h.265 and MP3.", - "section": "WebEngine", "autoDetect": false, "output": [ "privateFeature" ] }, @@ -175,13 +158,11 @@ "webengine-spellchecker": { "label": "Spellchecker", "purpose": "Provides a spellchecker.", - "section": "WebEngine", "output": [ "publicFeature" ] }, "webengine-native-spellchecker": { "label": "Native Spellchecker", "purpose": "Use the system's native spellchecking engine.", - "section": "WebEngine", "autoDetect": false, "condition": "config.macos && features.webengine-spellchecker", "output": [ "publicFeature" ] @@ -197,38 +178,27 @@ "webengine-webrtc": { "label": "WebRTC", "purpose": "Provides WebRTC support.", - "section": "WebEngine", "autoDetect": "!features.webengine-embedded-build", "output": [ "privateFeature" ] }, - "webengine-ozone-x11" : { + "webengine-webrtc-pipewire": { + "label": "PipeWire over GIO", + "purpose": "Provides PipeWire support in WebRTC using GIO.", + "condition": "features.webengine-webrtc && libs.webengine-gio", + "autoDetect": "false", + "output": [ "privateFeature" ] + }, + "webengine-ozone" : { "label": "Support qpa-xcb", - "condition": "config.unix - && features.webengine-system-x11 - && features.webengine-system-libdrm - && features.webengine-system-xcomposite - && features.webengine-system-xcursor - && features.webengine-system-xi - && features.webengine-system-xtst", + "condition": "features.webengine-ozone-x11", "output": [ "privateFeature" ] }, - "webengine-sanitizer" : { - "label": "Sanitizer", - "autoDetect": "config.sanitizer && tests.webengine-sanitizer", - "condition": "config.sanitizer", - "output": [ "privateFeature" ] - }, "webengine-poppler-cpp": { "label": "poppler-cpp", "autoDetect": "config.unix", "condition": "libs.webengine-poppler-cpp", "output": [ "privateFeature" ] }, - "webengine-arm-thumb": { - "label": "Thumb instruction set", - "condition": "config.linux && features.webengine-embedded-build && arch.arm && tests.webengine-arm-thumb", - "output": [ "privateFeature" ] - }, "webengine-full-debug-info": { "label": "Full debug information", "purpose": "Enables debug information for Blink and V8.", @@ -238,22 +208,12 @@ { "type": "privateConfig", "name": "v8base_debug" }, { "type": "privateConfig", "name": "webcore_debug" } ] - }, - "webengine-noexecstack": { - "label": "linker supports -z noexecstack", - "condition": "config.unix && tests.webengine-noexecstack", - "output": [ "privateFeature" ] } }, "report": [ { "type": "warning", - "condition": "config.sanitizer && !tests.webengine-sanitizer && !features.webengine-sanitizer", - "message": "Qt WebEngine cannot be built with the chosen sanitizer configuration. Check config.log for details or use -feature-webengine-sanitizer to force the build." - }, - { - "type": "warning", "condition": "config.unix && !features.webengine-host-pkg-config", "message": "host pkg-config not found" }, @@ -264,7 +224,7 @@ }, { "type": "warning", - "condition": "config.linux && features.webengine-v8-snapshot && !features.webengine-v8-snapshot-support", + "condition": "config.unix && config.cross_compile && !features.webengine-v8-snapshot-support", "message": "V8 snapshot cannot be built. Most likely, the 32-bit host compiler does not work. Please make sure you have 32-bit devel environment installed." } ], @@ -282,20 +242,20 @@ "webengine-spellchecker", "webengine-native-spellchecker", "webengine-webrtc", + "webengine-webrtc-pipewire", "webengine-geolocation", "webengine-webchannel", - "webengine-v8-snapshot", "webengine-kerberos", "webengine-extensions", { "type": "feature", - "args": "webengine-ozone-x11", + "args": "webengine-ozone", "condition": "config.unix" }, { "type": "feature", "args": "webengine-v8-snapshot-support", - "condition": "config.unix && config.cross_compile && features.webengine-v8-snapshot" + "condition": "config.unix && config.cross_compile" }, { "type": "feature", @@ -308,11 +268,6 @@ "condition": "config.unix" }, { - "type": "feature", - "args": "webengine-sanitizer", - "condition": "config.sanitizer" - }, - { "message": "macOS version", "type": "macosToolchainVersion", "args": "macosVersion", diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index 12d986bb7..e15bd05f3 100644 --- a/src/core/content_browser_client_qt.cpp +++ b/src/core/content_browser_client_qt.cpp @@ -39,73 +39,52 @@ #include "content_browser_client_qt.h" -#include "base/memory/ptr_util.h" +#include "base/files/file_util.h" #include "base/optional.h" -#include "base/path_service.h" -#include "base/strings/utf_string_conversions.h" -#include "base/message_loop/message_loop.h" #include "base/task/post_task.h" -#include "base/threading/thread_restrictions.h" +#include "chrome/browser/custom_handlers/protocol_handler_registry.h" #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h" -#if QT_CONFIG(webengine_spellchecker) -#include "chrome/browser/spellchecker/spell_check_host_chrome_impl.h" -#endif +#include "chrome/browser/tab_contents/form_interaction_tab_helper.h" #include "components/navigation_interception/intercept_navigation_throttle.h" #include "components/navigation_interception/navigation_params.h" -#include "components/guest_view/browser/guest_view_base.h" -#include "components/network_hints/browser/network_hints_message_filter.h" -#include "content/browser/renderer_host/render_view_host_delegate.h" -#include "content/common/url_schemes.h" -#include "content/public/browser/browser_task_traits.h" +#include "components/network_hints/browser/simple_network_hints_handler_impl.h" +#include "components/performance_manager/embedder/performance_manager_registry.h" +#include "components/performance_manager/public/performance_manager.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/public/browser/browser_main_runner.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/client_certificate_delegate.h" +#include "content/public/browser/file_url_loader.h" #include "content/public/browser/media_observer.h" -#include "content/public/browser/network_service_instance.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" -#include "content/public/browser/resource_dispatcher_host.h" -#include "content/public/browser/resource_dispatcher_host_delegate.h" -#include "content/public/browser/storage_partition.h" +#include "content/public/browser/shared_cors_origin_access_list.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_user_data.h" #include "content/public/browser/web_ui_url_loader_factory.h" #include "content/public/common/content_switches.h" #include "content/public/common/main_function_params.h" -#include "content/public/common/service_manager_connection.h" #include "content/public/common/service_names.mojom.h" -#include "content/public/common/url_constants.h" #include "content/public/common/user_agent.h" -#include "media/media_buildflags.h" #include "extensions/buildflags/buildflags.h" -#include "extensions/browser/extension_protocols.h" -#include "extensions/browser/guest_view/web_view/web_view_guest.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/binding_set.h" -#include "mojo/public/cpp/bindings/remote.h" -#include "printing/buildflags/buildflags.h" -#include "qtwebengine/browser/qtwebengine_content_browser_overlay_manifest.h" -#include "qtwebengine/browser/qtwebengine_content_renderer_overlay_manifest.h" -#include "qtwebengine/browser/qtwebengine_packaged_service_manifest.h" -#include "qtwebengine/browser/qtwebengine_renderer_manifest.h" +#include "mojo/public/cpp/bindings/self_owned_associated_receiver.h" #include "net/ssl/client_cert_identity.h" #include "net/ssl/client_cert_store.h" #include "services/network/network_service.h" -#include "services/network/public/cpp/features.h" -#include "services/service_manager/public/cpp/connector.h" -#include "services/service_manager/public/cpp/service.h" -#include "services/service_manager/sandbox/switches.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" +#include "third_party/blink/public/common/loader/url_loader_throttle.h" #include "third_party/blink/public/mojom/insecure_input/insecure_input_service.mojom.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/ui_base_switches.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_implementation.h" -#include "ui/gl/gl_share_group.h" #include "ui/gl/gpu_timing.h" #include "url/url_util_qt.h" +#include "qtwebengine/browser/qtwebengine_content_browser_overlay_manifest.h" +#include "qtwebengine/browser/qtwebengine_content_renderer_overlay_manifest.h" #include "qtwebengine/common/renderer_configuration.mojom.h" #include "qtwebengine/grit/qt_webengine_resources.h" @@ -120,32 +99,27 @@ #include "media_capture_devices_dispatcher.h" #include "net/cookie_monster_delegate_qt.h" #include "net/custom_url_loader_factory.h" -#include "net/network_delegate_qt.h" #include "net/proxying_restricted_cookie_manager_qt.h" #include "net/proxying_url_loader_factory_qt.h" -#include "net/qrc_url_scheme_handler.h" -#include "net/url_request_context_getter_qt.h" #include "net/system_network_context_manager.h" #include "platform_notification_service_qt.h" -#if QT_CONFIG(webengine_printing_and_pdf) -#include "printing/printing_message_filter_qt.h" -#endif #include "profile_qt.h" #include "profile_io_data_qt.h" #include "quota_permission_context_qt.h" #include "renderer_host/user_resource_controller_host.h" -#include "service/service_qt.h" #include "type_conversion.h" #include "web_contents_adapter_client.h" +#include "web_contents_adapter.h" #include "web_contents_delegate_qt.h" +#include "web_contents_view_qt.h" #include "web_engine_context.h" #include "web_engine_library_info.h" #include "api/qwebenginecookiestore.h" #include "api/qwebenginecookiestore_p.h" -#if defined(Q_OS_LINUX) -#include "global_descriptors_qt.h" -#include "ui/base/resource/resource_bundle.h" +#if QT_CONFIG(webengine_geolocation) +#include "base/memory/ptr_util.h" +#include "location_provider_qt.h" #endif #if QT_CONFIG(webengine_pepper_plugins) @@ -154,18 +128,42 @@ #include "renderer_host/pepper/pepper_host_factory_qt.h" #endif -#if QT_CONFIG(webengine_geolocation) -#include "location_provider_qt.h" +#if QT_CONFIG(webengine_printing_and_pdf) +#include "printing/printing_message_filter_qt.h" +#endif + +#if QT_CONFIG(webengine_spellchecker) +#include "chrome/browser/spellchecker/spell_check_host_chrome_impl.h" +#include "components/spellcheck/common/spellcheck.mojom.h" +#endif + +#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) +#include "chrome/browser/media/webrtc/webrtc_logging_controller.h" +#endif + +#if defined(Q_OS_LINUX) +#include "global_descriptors_qt.h" #endif #if BUILDFLAG(ENABLE_EXTENSIONS) -#include "extensions/extensions_browser_client_qt.h" +#include "common/extensions/extensions_client_qt.h" +#include "components/guest_view/browser/guest_view_base.h" +#include "extensions/browser/api/mime_handler_private/mime_handler_private.h" #include "extensions/browser/extension_message_filter.h" +#include "extensions/browser/extension_protocols.h" +#include "extensions/browser/extension_registry.h" +#include "extensions/browser/extension_util.h" #include "extensions/browser/guest_view/extensions_guest_view_message_filter.h" -#include "extensions/browser/io_thread_extension_message_filter.h" +#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h" +#include "extensions/browser/guest_view/web_view/web_view_guest.h" +#include "extensions/browser/process_map.h" +#include "extensions/browser/url_loader_factory_manager.h" #include "extensions/common/constants.h" -#include "common/extensions/extensions_client_qt.h" -#include "renderer_host/resource_dispatcher_host_delegate_qt.h" +#include "extensions/common/manifest_handlers/mime_types_handler.h" +#include "extensions/extension_web_contents_observer_qt.h" +#include "extensions/extensions_browser_client_qt.h" +#include "extensions/pdf_iframe_navigation_throttle_qt.h" +#include "net/plugin_response_interceptor_url_loader_throttle.h" #endif #if BUILDFLAG(ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS) @@ -174,105 +172,52 @@ #endif #include <QGuiApplication> -#include <QLocale> #include <QStandardPaths> -#if QT_CONFIG(opengl) -# include <QOpenGLContext> -# include <QOpenGLExtraFunctions> -#endif -#include <qpa/qplatformnativeinterface.h> - -QT_BEGIN_NAMESPACE -Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context(); -QT_END_NAMESPACE - -namespace QtWebEngineCore { -class QtShareGLContext : public gl::GLContext { -public: - QtShareGLContext(QOpenGLContext *qtContext) - : gl::GLContext(0) - , m_handle(0) - { - QString platform = qApp->platformName().toLower(); - QPlatformNativeInterface *pni = QGuiApplication::platformNativeInterface(); - if (platform == QLatin1String("xcb") || platform == QLatin1String("offscreen")) { - if (gl::GetGLImplementation() == gl::kGLImplementationEGLGLES2) - m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglcontext"), qtContext); - else - m_handle = pni->nativeResourceForContext(QByteArrayLiteral("glxcontext"), qtContext); - } else if (platform == QLatin1String("cocoa")) - m_handle = pni->nativeResourceForContext(QByteArrayLiteral("cglcontextobj"), qtContext); - else if (platform == QLatin1String("qnx")) - m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglcontext"), qtContext); - else if (platform == QLatin1String("eglfs") || platform == QLatin1String("wayland") - || platform == QLatin1String("wayland-egl")) - m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglcontext"), qtContext); - else if (platform == QLatin1String("windows")) { - if (gl::GetGLImplementation() == gl::kGLImplementationEGLGLES2) - m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglContext"), qtContext); - else - m_handle = pni->nativeResourceForContext(QByteArrayLiteral("renderingcontext"), qtContext); - } else { - qFatal("%s platform not yet supported", platform.toLatin1().constData()); - // Add missing platforms once they work. - Q_UNREACHABLE(); - } - } - - void* GetHandle() override { return m_handle; } - unsigned int CheckStickyGraphicsResetStatus() override - { -#if QT_CONFIG(opengl) - if (QOpenGLContext *context = qt_gl_global_share_context()) { - if (context->format().testOption(QSurfaceFormat::ResetNotification)) - return context->extraFunctions()->glGetGraphicsResetStatus(); - } +// Implement IsHandledProtocol as declared in //url/url_util_qt.h. +namespace url { +bool IsHandledProtocol(base::StringPiece scheme) +{ + static const char *const kProtocolList[] = { + url::kHttpScheme, + url::kHttpsScheme, +#if BUILDFLAG(ENABLE_WEBSOCKETS) + url::kWsScheme, + url::kWssScheme, +#endif // BUILDFLAG(ENABLE_WEBSOCKETS) + url::kFileScheme, + content::kChromeDevToolsScheme, +#if BUILDFLAG(ENABLE_EXTENSIONS) + extensions::kExtensionScheme, #endif - return 0 /*GL_NO_ERROR*/; - } + content::kChromeUIScheme, + url::kDataScheme, + url::kAboutScheme, +#if !BUILDFLAG(DISABLE_FTP_SUPPORT) + url::kFtpScheme, +#endif // !BUILDFLAG(DISABLE_FTP_SUPPORT) + url::kBlobScheme, + url::kFileSystemScheme, + url::kQrcScheme, + }; - // We don't care about the rest, this context shouldn't be used except for its handle. - bool Initialize(gl::GLSurface *, const gl::GLContextAttribs &) override { Q_UNREACHABLE(); return false; } - bool MakeCurrent(gl::GLSurface *) override { Q_UNREACHABLE(); return false; } - void ReleaseCurrent(gl::GLSurface *) override { Q_UNREACHABLE(); } - bool IsCurrent(gl::GLSurface *) override { Q_UNREACHABLE(); return false; } - scoped_refptr<gl::GPUTimingClient> CreateGPUTimingClient() override - { - return nullptr; - } - const gfx::ExtensionSet& GetExtensions() override - { - static const gfx::ExtensionSet s_emptySet; - return s_emptySet; - } - void ResetExtensions() override - { + for (const char *protocol : kProtocolList) { + if (scheme == protocol) + return true; } + if (const auto cs = url::CustomScheme::FindScheme(scheme)) + return true; + return false; +} +} -private: - void *m_handle; -}; - -class ShareGroupQtQuick : public gl::GLShareGroup { -public: - gl::GLContext* GetContext() override { return m_shareContextQtQuick.get(); } - void AboutToAddFirstContext() override; - -private: - scoped_refptr<QtShareGLContext> m_shareContextQtQuick; -}; +namespace QtWebEngineCore { -void ShareGroupQtQuick::AboutToAddFirstContext() -{ -#ifndef QT_NO_OPENGL - // This currently has to be setup by ::main in all applications using QQuickWebEngineView with delegated rendering. - QOpenGLContext *shareContext = qt_gl_global_share_context(); - if (!shareContext) { - qFatal("QWebEngine: OpenGL resource sharing is not set up in QtQuick. Please make sure to call QtWebEngine::initialize() in your main() function before QCoreApplication is created."); - } - m_shareContextQtQuick = new QtShareGLContext(shareContext); -#endif +void MaybeAddThrottle( + std::unique_ptr<content::NavigationThrottle> maybe_throttle, + std::vector<std::unique_ptr<content::NavigationThrottle>>* throttles) { + if (maybe_throttle) + throttles->push_back(std::move(maybe_throttle)); } ContentBrowserClientQt::ContentBrowserClientQt() @@ -288,22 +233,18 @@ std::unique_ptr<content::BrowserMainParts> ContentBrowserClientQt::CreateBrowser return std::make_unique<BrowserMainPartsQt>(); } -void ContentBrowserClientQt::RenderProcessWillLaunch(content::RenderProcessHost* host, - service_manager::mojom::ServiceRequest *service_request) +void ContentBrowserClientQt::RenderProcessWillLaunch(content::RenderProcessHost *host) { const int id = host->GetID(); Profile *profile = Profile::FromBrowserContext(host->GetBrowserContext()); - if (profile->GetRequestContext()) { - base::PostTaskWithTraitsAndReplyWithResult( - FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&net::URLRequestContextGetter::GetURLRequestContext, base::Unretained(profile->GetRequestContext())), - base::BindOnce(&ContentBrowserClientQt::AddNetworkHintsMessageFilter, base::Unretained(this), id)); - } + +#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) + WebRtcLoggingController::AttachToRenderProcessHost(host, WebEngineContext::current()->webRtcLogUploader()); +#endif // Allow requesting custom schemes. const auto policy = content::ChildProcessSecurityPolicy::GetInstance(); - const auto profileQt = static_cast<ProfileQt *>(host->GetBrowserContext()); - const auto profileAdapter = profileQt->profileAdapter(); + const auto profileAdapter = static_cast<ProfileQt *>(profile)->profileAdapter(); for (const QByteArray &scheme : profileAdapter->customUrlSchemes()) policy->GrantRequestScheme(id, scheme.toStdString()); @@ -312,46 +253,17 @@ void ContentBrowserClientQt::RenderProcessWillLaunch(content::RenderProcessHost* profileAdapter->userResourceController()->renderProcessStartedWithHost(host); host->AddFilter(new BrowserMessageFilterQt(id, profile)); #if QT_CONFIG(webengine_printing_and_pdf) - host->AddFilter(new PrintingMessageFilterQt(host->GetID())); + host->AddFilter(new PrintingMessageFilterQt(id)); #endif #if BUILDFLAG(ENABLE_EXTENSIONS) - host->AddFilter(new extensions::ExtensionMessageFilter(host->GetID(), host->GetBrowserContext())); - host->AddFilter(new extensions::IOThreadExtensionMessageFilter(host->GetID(), host->GetBrowserContext())); - host->AddFilter(new extensions::ExtensionsGuestViewMessageFilter(host->GetID(), host->GetBrowserContext())); + host->AddFilter(new extensions::ExtensionMessageFilter(id, profile)); + host->AddFilter(new extensions::ExtensionsGuestViewMessageFilter(id, profile)); #endif //ENABLE_EXTENSIONS bool is_incognito_process = profile->IsOffTheRecord(); - qtwebengine::mojom::RendererConfigurationAssociatedPtr renderer_configuration; + mojo::AssociatedRemote<qtwebengine::mojom::RendererConfiguration> renderer_configuration; host->GetChannel()->GetRemoteAssociatedInterface(&renderer_configuration); renderer_configuration->SetInitialConfiguration(is_incognito_process); - - mojo::PendingRemote<service_manager::mojom::Service> service; - *service_request = service.InitWithNewPipeAndPassReceiver(); - service_manager::Identity renderer_identity = host->GetChildIdentity(); - mojo::Remote<service_manager::mojom::ProcessMetadata> metadata; - ServiceQt::GetInstance()->connector()->RegisterServiceInstance( - service_manager::Identity("qtwebengine_renderer", - renderer_identity.instance_group(), - renderer_identity.instance_id(), - base::Token::CreateRandom()), - std::move(service), metadata.BindNewPipeAndPassReceiver()); -} - -void ContentBrowserClientQt::ResourceDispatcherHostCreated() -{ -#if BUILDFLAG(ENABLE_EXTENSIONS) - m_resourceDispatcherHostDelegate.reset(new ResourceDispatcherHostDelegateQt); -#else - m_resourceDispatcherHostDelegate.reset(new content::ResourceDispatcherHostDelegate); -#endif - content::ResourceDispatcherHost::Get()->SetDelegate(m_resourceDispatcherHostDelegate.get()); -} - -gl::GLShareGroup *ContentBrowserClientQt::GetInProcessGpuShareGroup() -{ - if (!m_shareGroupQtQuick.get()) - m_shareGroupQtQuick = new ShareGroupQtQuick; - return m_shareGroupQtQuick.get(); } content::MediaObserver *ContentBrowserClientQt::GetMediaObserver() @@ -359,12 +271,16 @@ content::MediaObserver *ContentBrowserClientQt::GetMediaObserver() return MediaCaptureDevicesDispatcher::GetInstance(); } -void ContentBrowserClientQt::OverrideWebkitPrefs(content::RenderViewHost *rvh, content::WebPreferences *web_prefs) +void ContentBrowserClientQt::OverrideWebkitPrefs(content::RenderViewHost *rvh, blink::web_pref::WebPreferences *web_prefs) { if (content::WebContents *webContents = rvh->GetDelegate()->GetAsWebContents()) { #if BUILDFLAG(ENABLE_EXTENSIONS) if (guest_view::GuestViewBase::IsGuest(webContents)) return; + + WebContentsViewQt *view = WebContentsViewQt::from(static_cast<content::WebContentsImpl *>(webContents)->GetView()); + if (!view->client()) + return; #endif // BUILDFLAG(ENABLE_EXTENSIONS) WebContentsDelegateQt* delegate = static_cast<WebContentsDelegateQt*>(webContents->GetDelegate()); if (delegate) @@ -377,13 +293,6 @@ scoped_refptr<content::QuotaPermissionContext> ContentBrowserClientQt::CreateQuo return new QuotaPermissionContextQt; } -void ContentBrowserClientQt::GetQuotaSettings(content::BrowserContext* context, - content::StoragePartition* partition, - storage::OptionalQuotaSettingsCallback callback) -{ - storage::GetNominalDynamicSettings(partition->GetPath(), context->IsOffTheRecord(), storage::GetDefaultDiskInfoHelper(), std::move(callback)); -} - // Copied from chrome/browser/ssl/ssl_error_handler.cc: static int IsCertErrorFatal(int cert_error) { @@ -391,17 +300,20 @@ static int IsCertErrorFatal(int cert_error) case net::ERR_CERT_COMMON_NAME_INVALID: case net::ERR_CERT_DATE_INVALID: case net::ERR_CERT_AUTHORITY_INVALID: + case net::ERR_CERT_NO_REVOCATION_MECHANISM: + case net::ERR_CERT_UNABLE_TO_CHECK_REVOCATION: case net::ERR_CERT_WEAK_SIGNATURE_ALGORITHM: case net::ERR_CERT_WEAK_KEY: case net::ERR_CERT_NAME_CONSTRAINT_VIOLATION: case net::ERR_CERT_VALIDITY_TOO_LONG: case net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED: case net::ERR_CERT_SYMANTEC_LEGACY: + case net::ERR_CERT_KNOWN_INTERCEPTION_BLOCKED: + case net::ERR_SSL_OBSOLETE_VERSION: return false; case net::ERR_CERT_CONTAINS_ERRORS: case net::ERR_CERT_REVOKED: case net::ERR_CERT_INVALID: - case net::ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY: case net::ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN: return true; default: @@ -416,8 +328,7 @@ void ContentBrowserClientQt::AllowCertificateError(content::WebContents *webCont const GURL &request_url, bool is_main_frame_request, bool strict_enforcement, - bool expired_previous_decision, - const base::Callback<void(content::CertificateRequestResultType)> &callback) + base::OnceCallback<void(content::CertificateRequestResultType)> callback) { WebContentsDelegateQt* contentsDelegate = static_cast<WebContentsDelegateQt*>(webContents->GetDelegate()); @@ -430,7 +341,7 @@ void ContentBrowserClientQt::AllowCertificateError(content::WebContents *webCont is_main_frame_request, IsCertErrorFatal(cert_error), strict_enforcement, - callback))); + std::move(callback)))); contentsDelegate->allowCertificateError(errorController); } @@ -454,12 +365,12 @@ base::OnceClosure ContentBrowserClientQt::SelectClientCertificate(content::WebCo return base::OnceClosure(); } -std::unique_ptr<net::ClientCertStore> ContentBrowserClientQt::CreateClientCertStore(content::ResourceContext *resource_context) +std::unique_ptr<net::ClientCertStore> ContentBrowserClientQt::CreateClientCertStore(content::BrowserContext *browser_context) { - if (!resource_context) + if (!browser_context) return nullptr; - return ProfileIODataQt::FromResourceContext(resource_context)->CreateClientCertStore(); + return ProfileIODataQt::FromBrowserContext(browser_context)->CreateClientCertStore(); } std::string ContentBrowserClientQt::GetApplicationLocale() @@ -479,26 +390,37 @@ void ContentBrowserClientQt::AppendExtraCommandLineSwitches(base::CommandLine* c url::CustomScheme::SaveSchemes(command_line); std::string processType = command_line->GetSwitchValueASCII(switches::kProcessType); - if (processType == service_manager::switches::kZygoteProcess) - command_line->AppendSwitchASCII(switches::kLang, GetApplicationLocale()); + if (processType == switches::kZygoteProcess) + command_line->AppendSwitchASCII(switches::kLang, WebEngineLibraryInfo::getApplicationLocale()); } void ContentBrowserClientQt::GetAdditionalWebUISchemes(std::vector<std::string>* additional_schemes) { + ContentBrowserClient::GetAdditionalWebUISchemes(additional_schemes); additional_schemes->push_back(content::kChromeDevToolsScheme); } void ContentBrowserClientQt::GetAdditionalViewSourceSchemes(std::vector<std::string>* additional_schemes) { - additional_schemes->push_back(content::kChromeDevToolsScheme); + ContentBrowserClient::GetAdditionalViewSourceSchemes(additional_schemes); + +#if BUILDFLAG(ENABLE_EXTENSIONS) + additional_schemes->push_back(extensions::kExtensionScheme); +#endif +} + +void ContentBrowserClientQt::GetAdditionalAllowedSchemesForFileSystem(std::vector<std::string>* additional_schemes) +{ + ContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem(additional_schemes); + additional_schemes->push_back(content::kChromeDevToolsScheme); + additional_schemes->push_back(content::kChromeUIScheme); } #if defined(Q_OS_LINUX) void ContentBrowserClientQt::GetAdditionalMappedFilesForChildProcess(const base::CommandLine& command_line, int child_process_id, content::PosixFileDescriptorInfo* mappings) { - const std::string &locale = GetApplicationLocale(); - const base::FilePath &locale_file_path = ui::ResourceBundle::GetSharedInstance().GetLocaleFilePath(locale, true); - if (locale_file_path.empty()) + const base::FilePath &locale_file_path = ui::ResourceBundle::GetSharedInstance().GetLocaleFilePath(WebEngineLibraryInfo::getResolvedLocale()); + if (locale_file_path.empty() || !base::PathExists(locale_file_path)) return; // Open pak file of the current locale in the Browser process and pass its file descriptor to the sandboxed @@ -542,7 +464,6 @@ public: if (!web_contents) return; CreateForWebContents(web_contents); - } static ServiceDriver* FromRenderFrameHost(content::RenderFrameHost *renderFrameHost) { @@ -551,17 +472,17 @@ public: return nullptr; return FromWebContents(web_contents); } - static void BindInsecureInputService(blink::mojom::InsecureInputServiceRequest request, content::RenderFrameHost *render_frame_host) + static void BindInsecureInputService(content::RenderFrameHost *render_frame_host, mojo::PendingReceiver<blink::mojom::InsecureInputService> receiver) { CreateForRenderFrameHost(render_frame_host); ServiceDriver *driver = FromRenderFrameHost(render_frame_host); if (driver) - driver->BindInsecureInputServiceRequest(std::move(request)); + driver->BindInsecureInputServiceReceiver(std::move(receiver)); } - void BindInsecureInputServiceRequest(blink::mojom::InsecureInputServiceRequest request) + void BindInsecureInputServiceReceiver(mojo::PendingReceiver<blink::mojom::InsecureInputService> receiver) { - m_insecureInputServiceBindings.AddBinding(this, std::move(request)); + m_receivers.Add(this, std::move(receiver)); } // blink::mojom::InsecureInputService: @@ -572,49 +493,96 @@ private: WEB_CONTENTS_USER_DATA_KEY_DECL(); explicit ServiceDriver(content::WebContents* /*web_contents*/) { } friend class content::WebContentsUserData<ServiceDriver>; - mojo::BindingSet<blink::mojom::InsecureInputService> m_insecureInputServiceBindings; + mojo::ReceiverSet<blink::mojom::InsecureInputService> m_receivers; }; WEB_CONTENTS_USER_DATA_KEY_IMPL(ServiceDriver) -void ContentBrowserClientQt::InitFrameInterfaces() +void ContentBrowserClientQt::BindHostReceiverForRenderer(content::RenderProcessHost *render_process_host, + mojo::GenericPendingReceiver receiver) { - m_frameInterfaces = std::make_unique<service_manager::BinderRegistry>(); - m_frameInterfacesParameterized = std::make_unique<service_manager::BinderRegistryWithArgs<content::RenderFrameHost*>>(); - m_frameInterfacesParameterized->AddInterface(base::BindRepeating(&ServiceDriver::BindInsecureInputService)); +#if QT_CONFIG(webengine_spellchecker) + if (auto host_receiver = receiver.As<spellcheck::mojom::SpellCheckHost>()) { + SpellCheckHostChromeImpl::Create(render_process_host->GetID(), std::move(host_receiver)); + return; + } +#endif } -void ContentBrowserClientQt::BindInterfaceRequestFromFrame(content::RenderFrameHost* render_frame_host, - const std::string& interface_name, - mojo::ScopedMessagePipeHandle interface_pipe) +static void BindNetworkHintsHandler(content::RenderFrameHost *frame_host, + mojo::PendingReceiver<network_hints::mojom::NetworkHintsHandler> receiver) { - if (!m_frameInterfaces.get() && !m_frameInterfacesParameterized.get()) - InitFrameInterfaces(); + network_hints::SimpleNetworkHintsHandlerImpl::Create(frame_host, std::move(receiver)); +} - if (!m_frameInterfacesParameterized->TryBindInterface(interface_name, &interface_pipe, render_frame_host)) - m_frameInterfaces->TryBindInterface(interface_name, &interface_pipe); +#if BUILDFLAG(ENABLE_EXTENSIONS) +static void BindMimeHandlerService(content::RenderFrameHost *frame_host, + mojo::PendingReceiver<extensions::mime_handler::MimeHandlerService> + receiver) { + auto *web_contents = content::WebContents::FromRenderFrameHost(frame_host); + if (!web_contents) + return; + auto *guest_view = extensions::MimeHandlerViewGuest::FromWebContents(web_contents); + if (!guest_view) + return; + extensions::MimeHandlerServiceImpl::Create(guest_view->GetStreamWeakPtr(), std::move(receiver)); } -void ContentBrowserClientQt::RunServiceInstance(const service_manager::Identity &identity, - mojo::PendingReceiver<service_manager::mojom::Service> *receiver) +static void BindBeforeUnloadControl(content::RenderFrameHost *frame_host, + mojo::PendingReceiver<extensions::mime_handler::BeforeUnloadControl> + receiver) { + auto *web_contents = content::WebContents::FromRenderFrameHost(frame_host); + if (!web_contents) + return; + auto *guest_view = extensions::MimeHandlerViewGuest::FromWebContents(web_contents); + if (!guest_view) + return; + guest_view->FuseBeforeUnloadControl(std::move(receiver)); +} +#endif + +void ContentBrowserClientQt::RegisterBrowserInterfaceBindersForFrame( + content::RenderFrameHost *render_frame_host, + mojo::BinderMapWithContext<content::RenderFrameHost *> *map) { -#if BUILDFLAG(ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS) - if (identity.name() == media::mojom::kMediaServiceName) { - service_manager::Service::RunAsyncUntilTermination(media::CreateMediaService(std::move(*receiver))); + Q_UNUSED(render_frame_host); + map->Add<blink::mojom::InsecureInputService>(base::BindRepeating(&ServiceDriver::BindInsecureInputService)); + map->Add<network_hints::mojom::NetworkHintsHandler>(base::BindRepeating(&BindNetworkHintsHandler)); +#if BUILDFLAG(ENABLE_EXTENSIONS) + map->Add<extensions::mime_handler::MimeHandlerService>(base::BindRepeating(&BindMimeHandlerService)); + map->Add<extensions::mime_handler::BeforeUnloadControl>(base::BindRepeating(&BindBeforeUnloadControl)); + const GURL &site = render_frame_host->GetSiteInstance()->GetSiteURL(); + if (!site.SchemeIs(extensions::kExtensionScheme)) return; - } + content::BrowserContext *browser_context = render_frame_host->GetProcess()->GetBrowserContext(); + auto *extension = extensions::ExtensionRegistry::Get(browser_context) + ->enabled_extensions() + .GetByID(site.host()); + if (!extension) + return; + extensions::ExtensionsBrowserClient::Get()->RegisterBrowserInterfaceBindersForFrame(map, + render_frame_host, + extension); #endif +} - content::ContentBrowserClient::RunServiceInstance(identity, receiver); +void ContentBrowserClientQt::ExposeInterfacesToRenderer(service_manager::BinderRegistry *registry, + blink::AssociatedInterfaceRegistry *associated_registry, + content::RenderProcessHost *render_process_host) +{ + Q_UNUSED(associated_registry); + performance_manager::PerformanceManagerRegistry::GetInstance()->CreateProcessNodeAndExposeInterfacesToRendererProcess(registry, render_process_host); } -void ContentBrowserClientQt::RunServiceInstanceOnIOThread(const service_manager::Identity &identity, - mojo::PendingReceiver<service_manager::mojom::Service> *receiver) +void ContentBrowserClientQt::RunServiceInstance(const service_manager::Identity &identity, + mojo::PendingReceiver<service_manager::mojom::Service> *receiver) { - if (identity.name() == "qtwebengine") { - ServiceQt::GetInstance()->CreateServiceQtRequestHandler().Run(std::move(*receiver)); +#if BUILDFLAG(ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS) + if (identity.name() == media::mojom::kMediaServiceName) { + service_manager::Service::RunAsyncUntilTermination(media::CreateMediaService(std::move(*receiver))); return; } +#endif content::ContentBrowserClient::RunServiceInstance(identity, receiver); } @@ -623,17 +591,13 @@ base::Optional<service_manager::Manifest> ContentBrowserClientQt::GetServiceMani { if (name == content::mojom::kBrowserServiceName) return GetQtWebEngineContentBrowserOverlayManifest(); - else if (name == content::mojom::kRendererServiceName) - return GetQtWebEngineContentRendererOverlayManifest(); return base::nullopt; } std::vector<service_manager::Manifest> ContentBrowserClientQt::GetExtraServiceManifests() { - auto manifests = GetQtWebEnginePackagedServiceManifests(); - manifests.push_back(GetQtWebEngineRendererManifest()); - return manifests; + return { }; } bool ContentBrowserClientQt::CanCreateWindow( @@ -685,19 +649,6 @@ std::unique_ptr<device::LocationProvider> ContentBrowserClientQt::OverrideSystem } #endif -void ContentBrowserClientQt::AddNetworkHintsMessageFilter(int render_process_id, net::URLRequestContext *context) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - content::RenderProcessHost* host = content::RenderProcessHost::FromID(render_process_id); - if (!host) - return; - - content::BrowserMessageFilter *network_hints_message_filter = - new network_hints::NetworkHintsMessageFilter(render_process_id); - host->AddFilter(network_hints_message_filter); -} - bool ContentBrowserClientQt::ShouldEnableStrictSiteIsolation() { // mirroring AwContentBrowserClient, CastContentBrowserClient and @@ -706,89 +657,102 @@ bool ContentBrowserClientQt::ShouldEnableStrictSiteIsolation() } bool ContentBrowserClientQt::WillCreateRestrictedCookieManager(network::mojom::RestrictedCookieManagerRole role, - content::BrowserContext *browser_context, - const url::Origin &origin, - bool is_service_worker, - int process_id, - int routing_id, - network::mojom::RestrictedCookieManagerRequest *request) -{ - if (Profile::FromBrowserContext(browser_context)->GetRequestContext()) { - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&ProfileIODataQt::CreateRestrictedCookieManager, - ProfileIODataQt::FromBrowserContext(browser_context)->getWeakPtrOnUIThread(), - std::move(*request), - role, origin, is_service_worker, process_id, routing_id)); - return true; - } + content::BrowserContext *browser_context, + const url::Origin & /*origin*/, + const net::SiteForCookies & /*site_for_cookies*/, + const url::Origin & /*top_frame_origin*/, + bool is_service_worker, + int process_id, + int routing_id, + mojo::PendingReceiver<network::mojom::RestrictedCookieManager> *receiver) +{ + mojo::PendingReceiver<network::mojom::RestrictedCookieManager> orig_receiver = std::move(*receiver); - network::mojom::RestrictedCookieManagerRequest orig_request = std::move(*request); - network::mojom::RestrictedCookieManagerPtrInfo target_rcm_info; - *request = mojo::MakeRequest(&target_rcm_info); + mojo::PendingRemote<network::mojom::RestrictedCookieManager> target_rcm_remote; + *receiver = target_rcm_remote.InitWithNewPipeAndPassReceiver(); ProxyingRestrictedCookieManagerQt::CreateAndBind( ProfileIODataQt::FromBrowserContext(browser_context), - std::move(target_rcm_info), + std::move(target_rcm_remote), is_service_worker, process_id, routing_id, - std::move(orig_request)); + std::move(orig_receiver)); return false; // only made a proxy, still need the actual impl to be made. } -bool ContentBrowserClientQt::AllowAppCacheOnIO(const GURL &manifest_url, - const GURL &first_party, - content::ResourceContext *context) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - return ProfileIODataQt::FromResourceContext(context)->canGetCookies(toQt(first_party), toQt(manifest_url)); -} - bool ContentBrowserClientQt::AllowAppCache(const GURL &manifest_url, const GURL &first_party, + const base::Optional<url::Origin> &top_frame_origin, content::BrowserContext *context) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (!context || context->ShutdownStarted()) + return false; return static_cast<ProfileQt *>(context)->profileAdapter()->cookieStore()->d_func()->canAccessCookies(toQt(first_party), toQt(manifest_url)); } -bool ContentBrowserClientQt::AllowServiceWorker(const GURL &scope, - const GURL &first_party, - const GURL & /*script_url*/, - content::ResourceContext *context, - base::RepeatingCallback<content::WebContents*()> wc_getter) +content::AllowServiceWorkerResult +ContentBrowserClientQt::AllowServiceWorkerOnIO(const GURL &scope, + const GURL &site_for_cookies, + const base::Optional<url::Origin> & /*top_frame_origin*/, + const GURL & /*script_url*/, + content::ResourceContext *context) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); // FIXME: Chrome also checks if javascript is enabled here to check if has been disabled since the service worker // was started. - return ProfileIODataQt::FromResourceContext(context)->canGetCookies(toQt(first_party), toQt(scope)); + return ProfileIODataQt::FromResourceContext(context)->canGetCookies(toQt(site_for_cookies), toQt(scope)) + ? content::AllowServiceWorkerResult::Yes() + : content::AllowServiceWorkerResult::No(); +} + +content::AllowServiceWorkerResult +ContentBrowserClientQt::AllowServiceWorkerOnUI(const GURL &scope, + const GURL &site_for_cookies, + const base::Optional<url::Origin> & /*top_frame_origin*/, + const GURL & /*script_url*/, + content::BrowserContext *context) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (!context || context->ShutdownStarted()) + return content::AllowServiceWorkerResult::No(); + // FIXME: Chrome also checks if javascript is enabled here to check if has been disabled since the service worker + // was started. + return static_cast<ProfileQt *>(context)->profileAdapter()->cookieStore()->d_func()->canAccessCookies(toQt(site_for_cookies), toQt(scope)) + ? content::AllowServiceWorkerResult::Yes() + : content::AllowServiceWorkerResult::No(); } // We control worker access to FS and indexed-db using cookie permissions, this is mirroring Chromium's logic. void ContentBrowserClientQt::AllowWorkerFileSystem(const GURL &url, - content::ResourceContext *context, + content::BrowserContext *context, const std::vector<content::GlobalFrameRoutingId> &/*render_frames*/, - base::Callback<void(bool)> callback) + base::OnceCallback<void(bool)> callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - callback.Run(ProfileIODataQt::FromResourceContext(context)->canSetCookie(toQt(url), QByteArray(), toQt(url))); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (!context || context->ShutdownStarted()) + return std::move(callback).Run(false); + std::move(callback).Run( + static_cast<ProfileQt *>(context)->profileAdapter()->cookieStore()->d_func()->canAccessCookies(toQt(url), toQt(url))); } bool ContentBrowserClientQt::AllowWorkerIndexedDB(const GURL &url, - content::ResourceContext *context, + content::BrowserContext *context, const std::vector<content::GlobalFrameRoutingId> &/*render_frames*/) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - return ProfileIODataQt::FromResourceContext(context)->canSetCookie(toQt(url), QByteArray(), toQt(url)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (!context || context->ShutdownStarted()) + return false; + return static_cast<ProfileQt *>(context)->profileAdapter()->cookieStore()->d_func()->canAccessCookies(toQt(url), toQt(url)); } static void LaunchURL(const GURL& url, - const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter, + base::OnceCallback<content::WebContents*()> web_contents_getter, ui::PageTransition page_transition, bool is_main_frame, bool has_user_gesture) { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - content::WebContents* webContents = web_contents_getter.Run(); + content::WebContents* webContents = std::move(web_contents_getter).Run(); if (!webContents) return; @@ -799,43 +763,51 @@ static void LaunchURL(const GURL& url, protocolHandlerRegistry->IsHandledProtocol(url.scheme())) return; +#if BUILDFLAG(ENABLE_EXTENSIONS) + if (guest_view::GuestViewBase::IsGuest(webContents)) { + // Use parent / top level contents delegate for launching URLs from guest views. + webContents = guest_view::GuestViewBase::GetTopLevelWebContents(webContents); + if (!webContents) + return; + } +#endif //BUILDFLAG(ENABLE_EXTENSIONS) + WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt*>(webContents->GetDelegate()); contentsDelegate->launchExternalURL(toQt(url), page_transition, is_main_frame, has_user_gesture); } -bool ContentBrowserClientQt::HandleExternalProtocol( - const GURL &url, - content::ResourceRequestInfo::WebContentsGetter web_contents_getter, +bool ContentBrowserClientQt::HandleExternalProtocol(const GURL &url, + base::OnceCallback<content::WebContents*()> web_contents_getter, int child_id, content::NavigationUIData *navigation_data, bool is_main_frame, ui::PageTransition page_transition, bool has_user_gesture, - network::mojom::URLLoaderFactoryPtr *out_factory) + const base::Optional<url::Origin> &initiating_origin, + mojo::PendingRemote<network::mojom::URLLoaderFactory> *out_factory) { -// Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); Q_UNUSED(child_id); Q_UNUSED(navigation_data); + Q_UNUSED(initiating_origin); Q_UNUSED(out_factory); - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&LaunchURL, - url, - web_contents_getter, - page_transition, - is_main_frame, - has_user_gesture)); + base::PostTask(FROM_HERE, {content::BrowserThread::UI}, + base::BindOnce(&LaunchURL, + url, + std::move(web_contents_getter), + page_transition, + is_main_frame, + has_user_gesture)); return true; } namespace { // Copied from chrome/browser/chrome_content_browser_client.cc -template<class HandlerRegistry> -class ProtocolHandlerThrottle : public content::URLLoaderThrottle +class ProtocolHandlerThrottle : public blink::URLLoaderThrottle { public: - explicit ProtocolHandlerThrottle(const HandlerRegistry &protocol_handler_registry) + explicit ProtocolHandlerThrottle(ProtocolHandlerRegistry *protocol_handler_registry) : protocol_handler_registry_(protocol_handler_registry) { } @@ -847,9 +819,11 @@ public: } void WillRedirectRequest(net::RedirectInfo *redirect_info, - const network::ResourceResponseHead &response_head, bool *defer, + const network::mojom::URLResponseHead &response_head, + bool *defer, std::vector<std::string> *to_be_removed_headers, - net::HttpRequestHeaders *modified_headers) override + net::HttpRequestHeaders *modified_headers, + net::HttpRequestHeaders *modified_cors_exempt_headers) override { TranslateUrl(&redirect_info->new_url); } @@ -864,37 +838,51 @@ private: *url = translated_url; } - HandlerRegistry protocol_handler_registry_; + ProtocolHandlerRegistry *protocol_handler_registry_; }; } // namespace -std::vector<std::unique_ptr<content::URLLoaderThrottle>> -ContentBrowserClientQt::CreateURLLoaderThrottlesOnIO( - const network::ResourceRequest & /*request*/, content::ResourceContext *resource_context, +std::vector<std::unique_ptr<blink::URLLoaderThrottle>> +ContentBrowserClientQt::CreateURLLoaderThrottles( + const network::ResourceRequest &request, content::BrowserContext *browser_context, const base::RepeatingCallback<content::WebContents *()> & /*wc_getter*/, - content::NavigationUIData * /*navigation_ui_data*/, int /*frame_tree_node_id*/) + content::NavigationUIData * /*navigation_ui_data*/, int frame_tree_node_id) { - std::vector<std::unique_ptr<content::URLLoaderThrottle>> result; - ProfileIODataQt *ioData = ProfileIODataQt::FromResourceContext(resource_context); - result.push_back(std::make_unique<ProtocolHandlerThrottle< - scoped_refptr<ProtocolHandlerRegistry::IOThreadDelegate>>>( - ioData->protocolHandlerRegistryIOThreadDelegate())); + std::vector<std::unique_ptr<blink::URLLoaderThrottle>> result; + result.push_back(std::make_unique<ProtocolHandlerThrottle>( + ProtocolHandlerRegistryFactory::GetForBrowserContext(browser_context))); +#if BUILDFLAG(ENABLE_EXTENSIONS) + result.push_back(std::make_unique<PluginResponseInterceptorURLLoaderThrottle>( + browser_context, request.resource_type, frame_tree_node_id)); +#endif return result; } -std::vector<std::unique_ptr<content::URLLoaderThrottle>> -ContentBrowserClientQt::CreateURLLoaderThrottles( - const network::ResourceRequest &request, content::BrowserContext *browser_context, - const base::RepeatingCallback<content::WebContents *()> &wc_getter, - content::NavigationUIData *navigation_ui_data, int frame_tree_node_id) +WebContentsAdapterClient::NavigationType pageTransitionToNavigationType(ui::PageTransition transition) { - std::vector<std::unique_ptr<content::URLLoaderThrottle>> result; - result.push_back(std::make_unique<ProtocolHandlerThrottle<ProtocolHandlerRegistry *>>( - ProtocolHandlerRegistryFactory::GetForBrowserContext(browser_context))); - return result; -} + if (ui::PageTransitionIsRedirect(transition)) + return WebContentsAdapterClient::RedirectNavigation; -extern WebContentsAdapterClient::NavigationType pageTransitionToNavigationType(ui::PageTransition transition); + int32_t qualifier = ui::PageTransitionGetQualifier(transition); + + if (qualifier & ui::PAGE_TRANSITION_FORWARD_BACK) + return WebContentsAdapterClient::BackForwardNavigation; + + ui::PageTransition strippedTransition = ui::PageTransitionStripQualifier(transition); + + switch (strippedTransition) { + case ui::PAGE_TRANSITION_LINK: + return WebContentsAdapterClient::LinkNavigation; + case ui::PAGE_TRANSITION_TYPED: + return WebContentsAdapterClient::TypedNavigation; + case ui::PAGE_TRANSITION_FORM_SUBMIT: + return WebContentsAdapterClient::FormSubmittedNavigation; + case ui::PAGE_TRANSITION_RELOAD: + return WebContentsAdapterClient::ReloadNavigation; + default: + return WebContentsAdapterClient::OtherNavigation; + } +} static bool navigationThrottleCallback(content::WebContents *source, const navigation_interception::NavigationParams ¶ms) @@ -905,10 +893,24 @@ static bool navigationThrottleCallback(content::WebContents *source, ProfileQt *profile = static_cast<ProfileQt *>(source->GetBrowserContext()); if (params.is_external_protocol() && !profile->profileAdapter()->urlSchemeHandler(toQByteArray(params.url().scheme()))) return false; + + WebContentsViewQt *view = WebContentsViewQt::from(static_cast<content::WebContentsImpl *>(source)->GetView()); + if (!view->client()) + return false; + int navigationRequestAction = WebContentsAdapterClient::AcceptRequest; - WebContentsDelegateQt *delegate = static_cast<WebContentsDelegateQt *>(source->GetDelegate()); - WebContentsAdapterClient *client = delegate->adapterClient(); - client->navigationRequested(pageTransitionToNavigationType(params.transition_type()), + + WebContentsAdapterClient *client = + WebContentsViewQt::from(static_cast<content::WebContentsImpl *>(source)->GetView())->client(); + if (!client) + return false; + + // Redirects might not be reflected in transition_type at this point (see also chrome/.../web_navigation_api_helpers.cc) + auto transition_type = params.transition_type(); + if (params.is_redirect()) + transition_type = ui::PageTransitionFromInt(transition_type | ui::PAGE_TRANSITION_SERVER_REDIRECT); + + client->navigationRequested(pageTransitionToNavigationType(transition_type), toQt(params.url()), navigationRequestAction, params.is_main_frame()); @@ -923,39 +925,17 @@ std::vector<std::unique_ptr<content::NavigationThrottle>> ContentBrowserClientQt navigation_handle, base::BindRepeating(&navigationThrottleCallback), navigation_interception::SynchronyMode::kSync)); - return throttles; -} -bool ContentBrowserClientQt::IsHandledURL(const GURL &url) -{ - static const char *const kProtocolList[] = { - url::kFileScheme, - content::kChromeDevToolsScheme, #if BUILDFLAG(ENABLE_EXTENSIONS) - extensions::kExtensionScheme, + MaybeAddThrottle(extensions::PDFIFrameNavigationThrottleQt::MaybeCreateThrottleFor(navigation_handle), &throttles); #endif - content::kChromeUIScheme, - url::kDataScheme, - url::kAboutScheme, -#if !BUILDFLAG(DISABLE_FTP_SUPPORT) - url::kFtpScheme, -#endif // !BUILDFLAG(DISABLE_FTP_SUPPORT) - url::kBlobScheme, - url::kFileSystemScheme, - url::kQrcScheme, - }; - // We don't check url.IsCustom() here because we don't - // know if the registered protocol is installed in the - // profile that will be used to load the URL. - - const std::string scheme = url.scheme(); + return throttles; +} - for (const char *protocol : kProtocolList) { - if (scheme == protocol) - return true; - } - return net::URLRequest::IsHandledProtocol(scheme); +bool ContentBrowserClientQt::IsHandledURL(const GURL &url) +{ + return url::IsHandledProtocol(url.scheme()); } std::unique_ptr<content::LoginDelegate> ContentBrowserClientQt::CreateLoginDelegate( @@ -987,14 +967,56 @@ bool ContentBrowserClientQt::ShouldUseProcessPerSite(content::BrowserContext* br return ContentBrowserClient::ShouldUseProcessPerSite(browser_context, effective_url); } -bool ContentBrowserClientQt::DoesSiteRequireDedicatedProcess(content::BrowserOrResourceContext browser_or_resource_context, +bool ContentBrowserClientQt::DoesSiteRequireDedicatedProcess(content::BrowserContext *browser_context, const GURL &effective_site_url) { #if BUILDFLAG(ENABLE_EXTENSIONS) if (effective_site_url.SchemeIs(extensions::kExtensionScheme)) return true; #endif - return ContentBrowserClient::DoesSiteRequireDedicatedProcess(browser_or_resource_context, effective_site_url); + return ContentBrowserClient::DoesSiteRequireDedicatedProcess(browser_context, effective_site_url); +} + +bool ContentBrowserClientQt::ShouldUseSpareRenderProcessHost(content::BrowserContext *browser_context, + const GURL &site_url) +{ +#if BUILDFLAG(ENABLE_EXTENSIONS) + if (site_url.SchemeIs(extensions::kExtensionScheme)) + return false; +#endif + return ContentBrowserClient::ShouldUseSpareRenderProcessHost(browser_context, site_url); +} + +bool ContentBrowserClientQt::ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(base::StringPiece scheme, bool is_embedded_origin_secure) +{ + if (is_embedded_origin_secure && scheme == content::kChromeUIScheme) + return true; +#if BUILDFLAG(ENABLE_EXTENSIONS) + return scheme == extensions::kExtensionScheme; +#else + return false; +#endif +} + +bool ContentBrowserClientQt::DoesSchemeAllowCrossOriginSharedWorker(const std::string &scheme) +{ +#if BUILDFLAG(ENABLE_EXTENSIONS) + // Extensions are allowed to start cross-origin shared workers. + return scheme == extensions::kExtensionScheme; +#else + return false; +#endif +} + +void ContentBrowserClientQt::OverrideURLLoaderFactoryParams(content::BrowserContext *browser_context, + const url::Origin &origin, + bool is_for_isolated_world, + network::mojom::URLLoaderFactoryParams *factory_params) +{ +#if BUILDFLAG(ENABLE_EXTENSIONS) + extensions::URLLoaderFactoryManager::OverrideURLLoaderFactoryParams( + browser_context, origin, is_for_isolated_world, factory_params); +#endif } std::string ContentBrowserClientQt::getUserAgent() @@ -1025,9 +1047,6 @@ network::mojom::NetworkContext *ContentBrowserClientQt::GetSystemNetworkContext( void ContentBrowserClientQt::OnNetworkServiceCreated(network::mojom::NetworkService *network_service) { - if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) - return; - if (!SystemNetworkContextManager::GetInstance()) SystemNetworkContextManager::CreateInstance(); @@ -1035,23 +1054,19 @@ void ContentBrowserClientQt::OnNetworkServiceCreated(network::mojom::NetworkServ SystemNetworkContextManager::GetInstance()->OnNetworkServiceCreated(network_service); } -network::mojom::NetworkContextPtr ContentBrowserClientQt::CreateNetworkContext(content::BrowserContext *context, - bool in_memory, - const base::FilePath &relative_partition_path) +void ContentBrowserClientQt::ConfigureNetworkContextParams( + content::BrowserContext *context, + bool in_memory, + const base::FilePath &relative_partition_path, + network::mojom::NetworkContextParams *network_context_params, + network::mojom::CertVerifierCreationParams *cert_verifier_creation_params) { - if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) - return nullptr; - - network::mojom::NetworkContextPtr network_context; - // ### do we need to pass in_memory and relative_partition_path to ProfileIODataQt::CreateNetworkContextParams() ? - network::mojom::NetworkContextParamsPtr context_params = ProfileIODataQt::FromBrowserContext(context)->CreateNetworkContextParams(); - content::GetNetworkService()->CreateNetworkContext(mojo::MakeRequest(&network_context), std::move(context_params)); - - network::mojom::CookieManagerPtrInfo cookie_manager_info; - network_context->GetCookieManager(mojo::MakeRequest(&cookie_manager_info)); - ProfileIODataQt::FromBrowserContext(context)->cookieDelegate()->setMojoCookieManager(std::move(cookie_manager_info)); + ProfileIODataQt::FromBrowserContext(context)->ConfigureNetworkContextParams(in_memory, relative_partition_path, + network_context_params, cert_verifier_creation_params); - return network_context; + mojo::PendingRemote<network::mojom::CookieManager> cookie_manager_remote; + network_context_params->cookie_manager = cookie_manager_remote.InitWithNewPipeAndPassReceiver(); + ProfileIODataQt::FromBrowserContext(context)->cookieDelegate()->setMojoCookieManager(std::move(cookie_manager_remote)); } std::vector<base::FilePath> ContentBrowserClientQt::GetNetworkContextsParentDirectory() @@ -1062,9 +1077,11 @@ std::vector<base::FilePath> ContentBrowserClientQt::GetNetworkContextsParentDire } void ContentBrowserClientQt::RegisterNonNetworkNavigationURLLoaderFactories(int frame_tree_node_id, + base::UkmSourceId ukm_source_id, + NonNetworkURLLoaderFactoryDeprecatedMap *uniquely_owned_factories, NonNetworkURLLoaderFactoryMap *factories) { - DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService)); + Q_UNUSED(uniquely_owned_factories); content::WebContents *web_contents = content::WebContents::FromFrameTreeNodeId(frame_tree_node_id); Profile *profile = Profile::FromBrowserContext(web_contents->GetBrowserContext()); ProfileAdapter *profileAdapter = static_cast<ProfileQt *>(profile)->profileAdapter(); @@ -1075,16 +1092,44 @@ void ContentBrowserClientQt::RegisterNonNetworkNavigationURLLoaderFactories(int #if BUILDFLAG(ENABLE_EXTENSIONS) factories->emplace( extensions::kExtensionScheme, - extensions::CreateExtensionNavigationURLLoaderFactory(profile, + extensions::CreateExtensionNavigationURLLoaderFactory(profile, ukm_source_id, !!extensions::WebViewGuest::FromWebContents(web_contents))); #endif } +void ContentBrowserClientQt::RegisterNonNetworkWorkerMainResourceURLLoaderFactories(content::BrowserContext *browser_context, + NonNetworkURLLoaderFactoryMap *factories) +{ + Profile *profile = Profile::FromBrowserContext(browser_context); + ProfileAdapter *profileAdapter = static_cast<ProfileQt *>(profile)->profileAdapter(); + + for (const QByteArray &scheme : profileAdapter->customUrlSchemes()) + factories->emplace(scheme.toStdString(), CreateCustomURLLoaderFactory(profileAdapter)); + +#if BUILDFLAG(ENABLE_EXTENSIONS) + factories->emplace( + extensions::kExtensionScheme, + extensions::CreateExtensionWorkerMainResourceURLLoaderFactory(browser_context)); +#endif // BUILDFLAG(ENABLE_EXTENSIONS) +} + +void ContentBrowserClientQt::RegisterNonNetworkServiceWorkerUpdateURLLoaderFactories(content::BrowserContext* browser_context, + NonNetworkURLLoaderFactoryMap* factories) +{ + DCHECK(browser_context); + DCHECK(factories); +#if BUILDFLAG(ENABLE_EXTENSIONS) + factories->emplace( + extensions::kExtensionScheme, + extensions::CreateExtensionServiceWorkerScriptURLLoaderFactory(browser_context)); +#endif // BUILDFLAG(ENABLE_EXTENSIONS) +} + void ContentBrowserClientQt::RegisterNonNetworkSubresourceURLLoaderFactories(int render_process_id, int render_frame_id, + NonNetworkURLLoaderFactoryDeprecatedMap *uniquely_owned_factories, NonNetworkURLLoaderFactoryMap *factories) { - if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) - return; + Q_UNUSED(uniquely_owned_factories); content::RenderProcessHost *process_host = content::RenderProcessHost::FromID(render_process_id); Profile *profile = Profile::FromBrowserContext(process_host->GetBrowserContext()); ProfileAdapter *profileAdapter = static_cast<ProfileQt *>(profile)->profileAdapter(); @@ -1092,39 +1137,170 @@ void ContentBrowserClientQt::RegisterNonNetworkSubresourceURLLoaderFactories(int for (const QByteArray &scheme : profileAdapter->customUrlSchemes()) factories->emplace(scheme.toStdString(), CreateCustomURLLoaderFactory(profileAdapter)); + content::RenderFrameHost *frame_host = content::RenderFrameHost::FromID(render_process_id, render_frame_id); + content::WebContents *web_contents = content::WebContents::FromRenderFrameHost(frame_host); + GURL url; + if (web_contents) + url = web_contents->GetVisibleURL(); + + // Install file scheme if necessary: + // FIXME: "extension -> file" will not be needed after switching to using transferable url loaders and guest views. + // FIXME: "qrc -> file" should be reconsidered for Qt6. + bool install_file_scheme = url.SchemeIs("qrc"); +#if BUILDFLAG(ENABLE_EXTENSIONS) + install_file_scheme = install_file_scheme || url.SchemeIs(extensions::kExtensionScheme); +#endif + if (!install_file_scheme && web_contents) { + const auto *settings = static_cast<WebContentsDelegateQt *>(web_contents->GetResponsibleWebContents()->GetDelegate())->webEngineSettings(); + if (settings->testAttribute(WebEngineSettings::LocalContentCanAccessFileUrls)) { + for (const auto &local_scheme : url::GetLocalSchemes()) { + if (url.SchemeIs(local_scheme)) { + install_file_scheme = true; + break; + } + } + } + } + + if (install_file_scheme && factories->find(url::kFileScheme) == factories->end()) { + auto file_factory = content::CreateFileURLLoaderFactory(profile->GetPath(), + profile->GetSharedCorsOriginAccessList()); + factories->emplace(url::kFileScheme, std::move(file_factory)); + } + #if BUILDFLAG(ENABLE_EXTENSIONS) auto factory = extensions::CreateExtensionURLLoaderFactory(render_process_id, render_frame_id); if (factory) factories->emplace(extensions::kExtensionScheme, std::move(factory)); + + if (!web_contents) + return; + + extensions::ExtensionWebContentsObserverQt *web_observer = + extensions::ExtensionWebContentsObserverQt::FromWebContents(web_contents); + if (!web_observer) + return; + + const extensions::Extension *extension = web_observer->GetExtensionFromFrame(frame_host, false); + if (!extension) + return; + + std::vector<std::string> allowed_webui_hosts; + // Support for chrome:// scheme if appropriate. + if ((extension->is_extension() || extension->is_platform_app()) && + extensions::Manifest::IsComponentLocation(extension->location())) { + // Components of chrome that are implemented as extensions or platform apps + // are allowed to use chrome://resources/ and chrome://theme/ URLs. + allowed_webui_hosts.emplace_back(content::kChromeUIResourcesHost); + } + if (!allowed_webui_hosts.empty()) { + factories->emplace(content::kChromeUIScheme, + content::CreateWebUIURLLoaderFactory(frame_host, + content::kChromeUIScheme, + std::move(allowed_webui_hosts))); + } +#endif +} + +base::flat_set<std::string> ContentBrowserClientQt::GetPluginMimeTypesWithExternalHandlers( + content::BrowserContext *browser_context) +{ + base::flat_set<std::string> mime_types; +#if BUILDFLAG(ENABLE_EXTENSIONS) + ProfileQt *profile = static_cast<ProfileQt *>(browser_context); + for (const std::string &extension_id : MimeTypesHandler::GetMIMETypeAllowlist()) { + const extensions::Extension *extension = + extensions::ExtensionRegistry::Get(browser_context) + ->enabled_extensions() + .GetByID(extension_id); + // The allowed extension may not be installed, so we have to nullptr + // check |extension|. + if (!extension || + (profile->IsOffTheRecord() && !extensions::util::IsIncognitoEnabled( + extension_id, browser_context))) { + continue; + } + if (MimeTypesHandler *handler = MimeTypesHandler::GetHandler(extension)) { + for (const auto &supported_mime_type : handler->mime_type_set()) + mime_types.insert(supported_mime_type); + } + } #endif + return mime_types; } bool ContentBrowserClientQt::WillCreateURLLoaderFactory( content::BrowserContext *browser_context, content::RenderFrameHost *frame, int render_process_id, - bool is_navigation, - bool is_download, + URLLoaderFactoryType type, const url::Origin &request_initiator, + base::Optional<int64_t> navigation_id, + base::UkmSourceId ukm_source_id, mojo::PendingReceiver<network::mojom::URLLoaderFactory> *factory_receiver, - network::mojom::TrustedURLLoaderHeaderClientPtrInfo *header_client, - bool *bypass_redirect_checks) + mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient> *header_client, + bool *bypass_redirect_checks, + bool *disable_secure_dns, + network::mojom::URLLoaderFactoryOverridePtr *factory_override) { - if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) - return false; - + auto adapter = static_cast<ProfileQt *>(browser_context)->profileAdapter(); + int process_id = type == URLLoaderFactoryType::kNavigation ? 0 : render_process_id; auto proxied_receiver = std::move(*factory_receiver); - network::mojom::URLLoaderFactoryPtrInfo target_factory_info; - *factory_receiver = mojo::MakeRequest(&target_factory_info); - int process_id = is_navigation ? 0 : render_process_id; - - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&ProxyingURLLoaderFactoryQt::CreateProxy, process_id, - browser_context->GetResourceContext(), - std::move(proxied_receiver), - std::move(target_factory_info))); + mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_url_loader_factory; + *factory_receiver = pending_url_loader_factory.InitWithNewPipeAndPassReceiver(); + // Will manage its own lifetime + new ProxyingURLLoaderFactoryQt(adapter, process_id, std::move(proxied_receiver), std::move(pending_url_loader_factory)); return true; } +void ContentBrowserClientQt::SiteInstanceGotProcess(content::SiteInstance *site_instance) +{ +#if BUILDFLAG(ENABLE_EXTENSIONS) + content::BrowserContext *context = site_instance->GetBrowserContext(); + extensions::ExtensionRegistry *registry = extensions::ExtensionRegistry::Get(context); + const extensions::Extension *extension = registry->enabled_extensions().GetExtensionOrAppByURL(site_instance->GetSiteURL()); + if (!extension) + return; + + extensions::ProcessMap *processMap = extensions::ProcessMap::Get(context); + processMap->Insert(extension->id(), site_instance->GetProcess()->GetID(), site_instance->GetId()); +#endif +} + +void ContentBrowserClientQt::SiteInstanceDeleting(content::SiteInstance *site_instance) +{ +#if BUILDFLAG(ENABLE_EXTENSIONS) + // Don't do anything if we're shutting down. + if (content::BrowserMainRunner::ExitedMainMessageLoop() || !site_instance->HasProcess()) + return; + + content::BrowserContext *context = site_instance->GetBrowserContext(); + extensions::ExtensionRegistry *registry = extensions::ExtensionRegistry::Get(context); + const extensions::Extension *extension = registry->enabled_extensions().GetExtensionOrAppByURL(site_instance->GetSiteURL()); + if (!extension) + return; + + extensions::ProcessMap *processMap = extensions::ProcessMap::Get(context); + processMap->Remove(extension->id(), site_instance->GetProcess()->GetID(), site_instance->GetId()); +#endif +} + +content::WebContentsViewDelegate *ContentBrowserClientQt::GetWebContentsViewDelegate(content::WebContents *web_contents) +{ + FormInteractionTabHelper::CreateForWebContents(web_contents); + if (auto *registry = performance_manager::PerformanceManagerRegistry::GetInstance()) + registry->MaybeCreatePageNodeForWebContents(web_contents); + + return nullptr; +} + +content::ContentBrowserClient::AllowWebBluetoothResult +ContentBrowserClientQt::AllowWebBluetooth(content::BrowserContext *browser_context, + const url::Origin &requesting_origin, + const url::Origin &embedding_origin) +{ + DCHECK(browser_context); + return content::ContentBrowserClient::AllowWebBluetoothResult::BLOCK_GLOBALLY_DISABLED; +} + } // namespace QtWebEngineCore diff --git a/src/core/content_browser_client_qt.h b/src/core/content_browser_client_qt.h index b58ccb8c4..06e2e9a20 100644 --- a/src/core/content_browser_client_qt.h +++ b/src/core/content_browser_client_qt.h @@ -41,13 +41,8 @@ #define CONTENT_BROWSER_CLIENT_QT_H #include "qtwebenginecoreglobal_p.h" -#include "base/memory/ref_counted.h" #include "content/public/browser/content_browser_client.h" -namespace net { -class URLRequestContextGetter; -} - namespace content { class BrowserContext; class BrowserMainParts; @@ -59,54 +54,37 @@ class BrowserPpapiHost; class DevToolsManagerDelegate; class RenderFrameHost; class RenderProcessHost; -class RenderViewHostDelegateView; class ResourceContext; -class ResourceDispatcherHostDelegate; -class WebContentsViewPort; class WebContents; struct MainFunctionParams; struct Referrer; } -namespace gl { -class GLShareGroup; -} - namespace QtWebEngineCore { -class BrowserMainPartsQt; -class ProfileQt; -class ShareGroupQtQuick; - -class ContentBrowserClientQt : public content::ContentBrowserClient { - +class ContentBrowserClientQt : public content::ContentBrowserClient +{ public: ContentBrowserClientQt(); ~ContentBrowserClientQt(); std::unique_ptr<content::BrowserMainParts> CreateBrowserMainParts(const content::MainFunctionParams&) override; - void RenderProcessWillLaunch(content::RenderProcessHost *host, - service_manager::mojom::ServiceRequest* service_request) override; - void ResourceDispatcherHostCreated() override; - gl::GLShareGroup* GetInProcessGpuShareGroup() override; + void RenderProcessWillLaunch(content::RenderProcessHost *host) override; content::MediaObserver* GetMediaObserver() override; scoped_refptr<content::QuotaPermissionContext> CreateQuotaPermissionContext() override; - void GetQuotaSettings(content::BrowserContext *context, - content::StoragePartition *partition, - storage::OptionalQuotaSettingsCallback callback) override; - void OverrideWebkitPrefs(content::RenderViewHost *, content::WebPreferences *) override; + void OverrideWebkitPrefs(content::RenderViewHost *render_view_host, + blink::web_pref::WebPreferences *prefs) override; void AllowCertificateError(content::WebContents *web_contents, int cert_error, const net::SSLInfo &ssl_info, const GURL &request_url, bool is_main_frame_request, bool strict_enforcement, - bool expired_previous_decision, - const base::Callback<void(content::CertificateRequestResultType)> &callback) override; + base::OnceCallback<void(content::CertificateRequestResultType)> callback) override; base::OnceClosure SelectClientCertificate(content::WebContents* web_contents, net::SSLCertRequestInfo* cert_request_info, net::ClientCertIdentityList client_certs, std::unique_ptr<content::ClientCertificateDelegate> delegate) override; - std::unique_ptr<net::ClientCertStore> CreateClientCertStore(content::ResourceContext *resource_context) override; + std::unique_ptr<net::ClientCertStore> CreateClientCertStore(content::BrowserContext *browser_context) override; content::DevToolsManagerDelegate *GetDevToolsManagerDelegate() override; content::PlatformNotificationService * GetPlatformNotificationService(content::BrowserContext *browser_context) override; @@ -116,14 +94,17 @@ public: void GetAdditionalViewSourceSchemes(std::vector<std::string>* additional_schemes) override; void GetAdditionalWebUISchemes(std::vector<std::string>* additional_schemes) override; + void GetAdditionalAllowedSchemesForFileSystem(std::vector<std::string>* additional_schemes) override; - void BindInterfaceRequestFromFrame(content::RenderFrameHost* render_frame_host, - const std::string& interface_name, - mojo::ScopedMessagePipeHandle interface_pipe) override; + void BindHostReceiverForRenderer(content::RenderProcessHost *render_process_host, + mojo::GenericPendingReceiver receiver) override; + void RegisterBrowserInterfaceBindersForFrame(content::RenderFrameHost *render_frame_host, + mojo::BinderMapWithContext<content::RenderFrameHost *> *map) override; void RunServiceInstance(const service_manager::Identity &identity, mojo::PendingReceiver<service_manager::mojom::Service> *receiver) override; - void RunServiceInstanceOnIOThread(const service_manager::Identity &identity, - mojo::PendingReceiver<service_manager::mojom::Service> *receiver) override; + void ExposeInterfacesToRenderer(service_manager::BinderRegistry *registry, + blink::AssociatedInterfaceRegistry *associated_registry, + content::RenderProcessHost *render_process_host) override; std::vector<service_manager::Manifest> GetExtraServiceManifests() override; base::Optional<service_manager::Manifest> GetServiceManifestOverlay(base::StringPiece name) override; @@ -142,44 +123,61 @@ public: bool *no_javascript_access) override; bool ShouldEnableStrictSiteIsolation() override; - bool WillCreateRestrictedCookieManager(network::mojom::RestrictedCookieManagerRole role, - content::BrowserContext *browser_context, - const url::Origin& origin, - bool is_service_worker, - int process_id, - int routing_id, - network::mojom::RestrictedCookieManagerRequest *request) override; - - bool AllowAppCacheOnIO(const GURL& manifest_url, - const GURL& first_party, - content::ResourceContext* context) override; - bool AllowAppCache(const GURL& manifest_url, - const GURL& first_party, - content::BrowserContext* context) override; - - bool AllowServiceWorker(const GURL& scope, - const GURL& first_party, - const GURL& script_url, - content::ResourceContext* context, - base::RepeatingCallback<content::WebContents*()> wc_getter) override; + bool WillCreateRestrictedCookieManager( + network::mojom::RestrictedCookieManagerRole role, + content::BrowserContext *browser_context, + const url::Origin &origin, + const net::SiteForCookies &site_for_cookies, + const url::Origin &top_frame_origin, + bool is_service_worker, + int process_id, + int routing_id, + mojo::PendingReceiver<network::mojom::RestrictedCookieManager> *receiver) override; + + bool AllowAppCache(const GURL &manifest_url, + const GURL &first_party, + const base::Optional<url::Origin> &top_frame_origin, + content::BrowserContext *context) override; + content::AllowServiceWorkerResult AllowServiceWorkerOnIO( + const GURL &scope, + const GURL &site_for_cookies, + const base::Optional<url::Origin> &top_frame_origin, + const GURL &script_url, + content::ResourceContext *context) override; + content::AllowServiceWorkerResult AllowServiceWorkerOnUI( + const GURL &scope, + const GURL &site_for_cookies, + const base::Optional<url::Origin> &top_frame_origin, + const GURL &script_url, + content::BrowserContext *context) override; void AllowWorkerFileSystem(const GURL &url, - content::ResourceContext *context, + content::BrowserContext *context, const std::vector<content::GlobalFrameRoutingId> &render_frames, - base::Callback<void(bool)> callback) override; + base::OnceCallback<void(bool)> callback) override; bool AllowWorkerIndexedDB(const GURL &url, - content::ResourceContext *context, + content::BrowserContext *context, const std::vector<content::GlobalFrameRoutingId> &render_frames) override; + AllowWebBluetoothResult AllowWebBluetooth(content::BrowserContext *browser_context, + const url::Origin &requesting_origin, + const url::Origin &embedding_origin) override; #if QT_CONFIG(webengine_geolocation) std::unique_ptr<device::LocationProvider> OverrideSystemLocationProvider() override; #endif bool ShouldIsolateErrorPage(bool in_main_frame) override; - bool ShouldUseProcessPerSite(content::BrowserContext* browser_context, const GURL& effective_url) override; - bool DoesSiteRequireDedicatedProcess(content::BrowserOrResourceContext browser_or_resource_contexts, + bool ShouldUseProcessPerSite(content::BrowserContext *browser_context, const GURL &effective_url) override; + bool DoesSiteRequireDedicatedProcess(content::BrowserContext *browser_context, const GURL &effective_site_url) override; - + bool ShouldUseSpareRenderProcessHost(content::BrowserContext *browser_context, const GURL& site_url) override; + bool ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(base::StringPiece scheme, + bool is_embedded_origin_secure) override; + bool DoesSchemeAllowCrossOriginSharedWorker(const std::string &scheme) override; + void OverrideURLLoaderFactoryParams(content::BrowserContext *browser_context, + const url::Origin &origin, + bool is_for_isolated_world, + network::mojom::URLLoaderFactoryParams *factory_params) override; #if defined(Q_OS_LINUX) void GetAdditionalMappedFilesForChildProcess(const base::CommandLine& command_line, int child_process_id, content::PosixFileDescriptorInfo* mappings) override; #endif @@ -200,20 +198,16 @@ public: bool HandleExternalProtocol( const GURL &url, - content::ResourceRequestInfo::WebContentsGetter web_contents_getter, + base::OnceCallback<content::WebContents*()> web_contents_getter, int child_id, content::NavigationUIData *navigation_data, bool is_main_frame, ui::PageTransition page_transition, bool has_user_gesture, - network::mojom::URLLoaderFactoryPtr *out_factory) override; - - std::vector<std::unique_ptr<content::URLLoaderThrottle>> CreateURLLoaderThrottlesOnIO( - const network::ResourceRequest &request, content::ResourceContext *resource_context, - const base::RepeatingCallback<content::WebContents *()> &wc_getter, - content::NavigationUIData *navigation_ui_data, int frame_tree_node_id) override; + const base::Optional<url::Origin> &initiating_origin, + mojo::PendingRemote<network::mojom::URLLoaderFactory> *out_factory) override; - std::vector<std::unique_ptr<content::URLLoaderThrottle>> CreateURLLoaderThrottles( + std::vector<std::unique_ptr<blink::URLLoaderThrottle>> CreateURLLoaderThrottles( const network::ResourceRequest &request, content::BrowserContext *browser_context, const base::RepeatingCallback<content::WebContents *()> &wc_getter, content::NavigationUIData *navigation_ui_data, int frame_tree_node_id) override; @@ -226,36 +220,45 @@ public: bool WillCreateURLLoaderFactory(content::BrowserContext *browser_context, content::RenderFrameHost *frame, int render_process_id, - bool is_navigation, - bool is_download, + URLLoaderFactoryType type, const url::Origin &request_initiator, + base::Optional<int64_t> navigation_id, + base::UkmSourceId ukm_source_id, mojo::PendingReceiver<network::mojom::URLLoaderFactory> *factory_receiver, - network::mojom::TrustedURLLoaderHeaderClientPtrInfo *header_client, - bool *bypass_redirect_checks) override; + mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient> *header_client, + bool *bypass_redirect_checks, + bool *disable_secure_dns, + network::mojom::URLLoaderFactoryOverridePtr *factory_override) override; scoped_refptr<network::SharedURLLoaderFactory> GetSystemSharedURLLoaderFactory() override; network::mojom::NetworkContext *GetSystemNetworkContext() override; void OnNetworkServiceCreated(network::mojom::NetworkService *network_service) override; - network::mojom::NetworkContextPtr CreateNetworkContext(content::BrowserContext *context, - bool in_memory, - const base::FilePath &relative_partition_path) override; + void ConfigureNetworkContextParams(content::BrowserContext *context, + bool in_memory, + const base::FilePath &relative_partition_path, + network::mojom::NetworkContextParams *network_context_params, + network::mojom::CertVerifierCreationParams *cert_verifier_creation_params) override; + std::vector<base::FilePath> GetNetworkContextsParentDirectory() override; - void RegisterNonNetworkNavigationURLLoaderFactories(int frame_tree_node_id, NonNetworkURLLoaderFactoryMap *factories) override; + void RegisterNonNetworkNavigationURLLoaderFactories(int frame_tree_node_id, base::UkmSourceId ukm_source_id, + NonNetworkURLLoaderFactoryDeprecatedMap *uniquely_owned_factories, + NonNetworkURLLoaderFactoryMap *factories) override; void RegisterNonNetworkSubresourceURLLoaderFactories(int render_process_id, int render_frame_id, - NonNetworkURLLoaderFactoryMap* factories) override; + NonNetworkURLLoaderFactoryDeprecatedMap *uniquely_owned_factories, + NonNetworkURLLoaderFactoryMap *factories) override; + void RegisterNonNetworkWorkerMainResourceURLLoaderFactories(content::BrowserContext* browser_context, + NonNetworkURLLoaderFactoryMap* factories) override; + void RegisterNonNetworkServiceWorkerUpdateURLLoaderFactories(content::BrowserContext* browser_context, + NonNetworkURLLoaderFactoryMap* factories) override; + void SiteInstanceGotProcess(content::SiteInstance *site_instance) override; + void SiteInstanceDeleting(content::SiteInstance *site_instance) override; + base::flat_set<std::string> GetPluginMimeTypesWithExternalHandlers(content::BrowserContext *browser_context) override; + + content::WebContentsViewDelegate* GetWebContentsViewDelegate(content::WebContents* web_contents) override; static std::string getUserAgent(); std::string GetUserAgent() override { return getUserAgent(); } std::string GetProduct() override; - -private: - void InitFrameInterfaces(); - void AddNetworkHintsMessageFilter(int render_process_id, net::URLRequestContext *context); - - std::unique_ptr<content::ResourceDispatcherHostDelegate> m_resourceDispatcherHostDelegate; - scoped_refptr<ShareGroupQtQuick> m_shareGroupQtQuick; - std::unique_ptr<service_manager::BinderRegistry> m_frameInterfaces; - std::unique_ptr<service_manager::BinderRegistryWithArgs<content::RenderFrameHost*>> m_frameInterfacesParameterized; }; } // namespace QtWebEngineCore diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp index 22f3f548f..560cdbf54 100644 --- a/src/core/content_client_qt.cpp +++ b/src/core/content_client_qt.cpp @@ -48,13 +48,15 @@ #include "base/version.h" #include "content/public/common/cdm_info.h" #include "content/public/common/content_constants.h" +#include "extensions/buildflags/buildflags.h" +#include "extensions/common/constants.h" #include "media/base/media_switches.h" #include "media/base/video_codecs.h" #include "media/media_buildflags.h" #include "ui/base/layout.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" - +#include "services/service_manager/switches.h" #include "type_conversion.h" #include <QCoreApplication> @@ -68,12 +70,10 @@ #include "third_party/widevine/cdm/widevine_cdm_common.h" #if BUILDFLAG(ENABLE_WIDEVINE) && !BUILDFLAG(ENABLE_WIDEVINE_CDM_COMPONENT) #define WIDEVINE_CDM_AVAILABLE_NOT_COMPONENT -namespace switches { -const char kCdmWidevinePath[] = "widevine-path"; -} + // File name of the CDM on different platforms. const char kWidevineCdmFileName[] = -#if defined(OS_MACOSX) +#if defined(OS_MAC) "widevinecdm.plugin"; #elif defined(OS_WIN) "widevinecdm.dll"; @@ -86,7 +86,7 @@ const char kWidevineCdmFileName[] = #include "pdf/pdf.h" #include "pdf/pdf_ppapi.h" const char kPdfPluginMimeType[] = "application/x-google-chrome-pdf"; -const char kPdfPluginPath[] = "internal-pdf-viewer/"; +const char kPdfPluginPath[] = "internal-pdf-viewer"; const char kPdfPluginSrc[] = "src"; #endif // QT_CONFIG(webengine_printing_and_pdf) @@ -114,6 +114,15 @@ static QString getLocalAppDataDir() result = QDir::fromNativeSeparators(QString::fromWCharArray(path)); return result; } + +static QString getProgramFilesDir(bool x86Dir = false) +{ + QString result; + wchar_t path[MAX_PATH]; + if (SHGetSpecialFolderPath(0, path, x86Dir ? CSIDL_PROGRAM_FILESX86 : CSIDL_PROGRAM_FILES, FALSE)) + result = QDir::fromNativeSeparators(QString::fromWCharArray(path)); + return result; +} #endif #if QT_CONFIG(webengine_pepper_plugins) @@ -192,7 +201,7 @@ void AddPepperFlashFromSystem(std::vector<content::PepperPluginInfo>* plugins) { QStringList pluginPaths; #if defined(Q_OS_WIN) - QString winDir = QDir::fromNativeSeparators(qgetenv("WINDIR")); + QString winDir = QDir::fromNativeSeparators(qEnvironmentVariable("WINDIR")); if (winDir.isEmpty()) winDir = QString::fromLatin1("C:/Windows"); QDir pluginDir(winDir + "/System32/Macromed/Flash"); @@ -278,7 +287,7 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path, content::CdmCapability *capability) { QStringList pluginPaths; - const base::CommandLine::StringType widevine_argument = base::CommandLine::ForCurrentProcess()->GetSwitchValueNative(switches::kCdmWidevinePath); + const base::CommandLine::StringType widevine_argument = base::CommandLine::ForCurrentProcess()->GetSwitchValueNative(service_manager::switches::kCdmWidevinePath); if (!widevine_argument.empty()) pluginPaths << QtWebEngineCore::toQt(widevine_argument); else { @@ -307,6 +316,28 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path, } } #elif defined(Q_OS_WIN) + const QString googleChromeDir = QLatin1String("/Google/Chrome/Application"); + const QStringList programFileDirs{getProgramFilesDir() + googleChromeDir, + getProgramFilesDir(true) + googleChromeDir}; + for (const QString &dir : programFileDirs) { + QDir d(dir); + if (d.exists()) { + QFileInfoList widevineVersionDirs = d.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); + for (int i = 0; i < widevineVersionDirs.size(); ++i) { + QString versionDirPath(widevineVersionDirs.at(i).absoluteFilePath()); +#ifdef WIN64 + QString potentialWidevinePluginPath = versionDirPath + + "/WidevineCdm/_platform_specific/win_x64/" + + QString::fromLatin1(kWidevineCdmFileName); +#else + QString potentialWidevinePluginPath = versionDirPath + + "/WidevineCdm/_platform_specific/win_x86/" + + QString::fromLatin1(kWidevineCdmFileName); +#endif + pluginPaths << potentialWidevinePluginPath; + } + } + } QDir potentialWidevineDir(getLocalAppDataDir() + "/Google/Chrome/User Data/WidevineCDM"); if (potentialWidevineDir.exists()) { QFileInfoList widevineVersionDirs = potentialWidevineDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); @@ -347,8 +378,8 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path, // Add the supported encryption schemes as if they came from the // component manifest. This list must match the CDM that is being // bundled with Chrome. - capability->encryption_schemes.insert(media::EncryptionMode::kCenc); - capability->encryption_schemes.insert(media::EncryptionMode::kCbcs); + capability->encryption_schemes.insert(media::EncryptionScheme::kCenc); + capability->encryption_schemes.insert(media::EncryptionScheme::kCbcs); // Temporary session is always supported. capability->session_types.insert(media::CdmSessionType::kTemporary); @@ -391,10 +422,9 @@ void ContentClientQt::AddContentDecryptionModules(std::vector<content::CdmInfo> // Supported codecs are hard-coded in ExternalClearKeyProperties. content::CdmCapability capability( - {}, {media::EncryptionMode::kCenc, media::EncryptionMode::kCbcs}, + {}, {media::EncryptionScheme::kCenc, media::EncryptionScheme::kCbcs}, {media::CdmSessionType::kTemporary, - media::CdmSessionType::kPersistentLicense}, - {}); + media::CdmSessionType::kPersistentLicense}); // Register kExternalClearKeyDifferentGuidTestKeySystem first separately. // Otherwise, it'll be treated as a sub-key-system of normal @@ -417,7 +447,15 @@ void ContentClientQt::AddContentDecryptionModules(std::vector<content::CdmInfo> void ContentClientQt::AddAdditionalSchemes(Schemes* schemes) { - schemes->standard_schemes.push_back("chrome-extension"); + // Matching ChromeContentClient::AddAdditionalSchemes + schemes->standard_schemes.push_back(extensions::kExtensionScheme); + schemes->secure_schemes.push_back(extensions::kExtensionScheme); + +#if BUILDFLAG(ENABLE_EXTENSIONS) + schemes->service_worker_schemes.push_back(extensions::kExtensionScheme); + schemes->cors_enabled_schemes.push_back(extensions::kExtensionScheme); + schemes->csp_bypassing_schemes.push_back(extensions::kExtensionScheme); +#endif } base::StringPiece ContentClientQt::GetDataResource(int resource_id, ui::ScaleFactor scale_factor) @@ -435,11 +473,6 @@ gfx::Image &ContentClientQt::GetNativeImageNamed(int resource_id) return ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(resource_id); } -bool ContentClientQt::IsDataResourceGzipped(int resource_id) -{ - return ui::ResourceBundle::GetSharedInstance().IsGzipped(resource_id); -} - base::string16 ContentClientQt::GetLocalizedString(int message_id) { return l10n_util::GetStringUTF16(message_id); diff --git a/src/core/content_client_qt.h b/src/core/content_client_qt.h index 581805a51..a7fc7432a 100644 --- a/src/core/content_client_qt.h +++ b/src/core/content_client_qt.h @@ -59,7 +59,6 @@ public: base::StringPiece GetDataResource(int, ui::ScaleFactor) override; base::RefCountedMemory* GetDataResourceBytes(int resource_id) override; gfx::Image &GetNativeImageNamed(int resource_id) override; - bool IsDataResourceGzipped(int resource_id) override; base::string16 GetLocalizedString(int message_id) override; }; diff --git a/src/core/content_main_delegate_qt.cpp b/src/core/content_main_delegate_qt.cpp index cb23a5287..6137b0bea 100644 --- a/src/core/content_main_delegate_qt.cpp +++ b/src/core/content_main_delegate_qt.cpp @@ -42,19 +42,22 @@ #include "base/command_line.h" #include "base/i18n/rtl.h" #include "base/logging.h" +#include "base/no_destructor.h" #include "base/path_service.h" #include "base/strings/string_number_conversions.h" #include "chrome/grit/generated_resources.h" #include "content/public/browser/browser_main_runner.h" #include "content/public/common/content_paths.h" #include "content/public/common/content_switches.h" +#include "media/gpu/buildflags.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/ui_base_paths.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/webui/jstemplate_builder.h" #include "net/grit/net_resources.h" #include "net/base/net_module.h" -#include "services/service_manager/sandbox/switches.h" +#include "sandbox/policy/switches.h" +#include "services/service_manager/switches.h" #include "url/url_util_qt.h" #include "content_client_qt.h" @@ -68,47 +71,79 @@ #endif #if defined(OS_LINUX) +#include "media/audio/audio_manager.h" #include "ui/base/ui_base_switches.h" #endif +// must be included before vaapi_wrapper.h #include <QtCore/qcoreapplication.h> +#if defined(OS_WIN) +#include "media/gpu/windows/dxva_video_decode_accelerator_win.h" +#include "media/gpu/windows/media_foundation_video_encode_accelerator_win.h" +#endif + +#if defined(OS_MAC) +#include "content/public/common/content_features.h" +#include "media/gpu/mac/vt_video_decode_accelerator_mac.h" +#endif + +#if BUILDFLAG(USE_VAAPI) +#include "media/gpu/vaapi/vaapi_wrapper.h" +#endif + namespace content { ContentClient *GetContentClient(); } namespace QtWebEngineCore { +namespace { + // The logic of this function is based on chrome/common/net/net_resource_provider.cc // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE.Chromium file. -static std::string constructDirHeaderHTML() -{ - base::DictionaryValue dict; - dict.SetString("header", l10n_util::GetStringUTF16(IDS_DIRECTORY_LISTING_HEADER)); - dict.SetString("parentDirText", l10n_util::GetStringUTF16(IDS_DIRECTORY_LISTING_PARENT)); - dict.SetString("headerName", l10n_util::GetStringUTF16(IDS_DIRECTORY_LISTING_NAME)); - dict.SetString("headerSize", l10n_util::GetStringUTF16(IDS_DIRECTORY_LISTING_SIZE)); - dict.SetString("headerDateModified", - l10n_util::GetStringUTF16(IDS_DIRECTORY_LISTING_DATE_MODIFIED)); - dict.SetString("language", l10n_util::GetLanguage(base::i18n::GetConfiguredLocale())); - dict.SetString("listingParsingErrorBoxText", - l10n_util::GetStringFUTF16(IDS_DIRECTORY_LISTING_PARSING_ERROR_BOX_TEXT, - toString16(QCoreApplication::applicationName()))); - dict.SetString("textdirection", base::i18n::IsRTL() ? "rtl" : "ltr"); - std::string html = webui::GetI18nTemplateHtml( - ui::ResourceBundle::GetSharedInstance().GetRawDataResource(IDR_DIR_HEADER_HTML), - &dict); - return html; -} -static base::StringPiece PlatformResourceProvider(int key) { - if (key == IDR_DIR_HEADER_HTML) { - static std::string html_data = constructDirHeaderHTML(); - return base::StringPiece(html_data); +// The net module doesn't have access to this HTML or the strings that need to +// be localized. The Chrome locale will never change while we're running, so +// it's safe to have a static string that we always return a pointer into. +struct LazyDirectoryListerCacher +{ + LazyDirectoryListerCacher() + { + base::DictionaryValue dict; + dict.SetString("header", l10n_util::GetStringUTF16(IDS_DIRECTORY_LISTING_HEADER)); + dict.SetString("parentDirText", l10n_util::GetStringUTF16(IDS_DIRECTORY_LISTING_PARENT)); + dict.SetString("headerName", l10n_util::GetStringUTF16(IDS_DIRECTORY_LISTING_NAME)); + dict.SetString("headerSize", l10n_util::GetStringUTF16(IDS_DIRECTORY_LISTING_SIZE)); + dict.SetString("headerDateModified", + l10n_util::GetStringUTF16(IDS_DIRECTORY_LISTING_DATE_MODIFIED)); + dict.SetString("language", l10n_util::GetLanguage(base::i18n::GetConfiguredLocale())); + dict.SetString("listingParsingErrorBoxText", + l10n_util::GetStringFUTF16(IDS_DIRECTORY_LISTING_PARSING_ERROR_BOX_TEXT, + toString16(QCoreApplication::applicationName()))); + dict.SetString("textdirection", base::i18n::IsRTL() ? "rtl" : "ltr"); + std::string html = + webui::GetI18nTemplateHtml( + ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(IDR_DIR_HEADER_HTML), + &dict); + html_data = base::RefCountedString::TakeString(&html); } - return base::StringPiece(); + + scoped_refptr<base::RefCountedMemory> html_data; +}; + +} // namespace + +static scoped_refptr<base::RefCountedMemory> PlatformResourceProvider(int key) +{ + static base::NoDestructor<LazyDirectoryListerCacher> lazy_dir_lister; + + if (IDR_DIR_HEADER_HTML == key) + return lazy_dir_lister->html_data; + + return ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytes(key); } // Logging logic is based on chrome/common/logging_chrome.cc: @@ -144,7 +179,9 @@ void ContentMainDelegateQt::PreSandboxStartup() #endif net::NetModule::SetResourceProvider(PlatformResourceProvider); - ui::ResourceBundle::InitSharedInstanceWithLocale(WebEngineLibraryInfo::getApplicationLocale(), 0, ui::ResourceBundle::LOAD_COMMON_RESOURCES); + + base::i18n::SetICUDefaultLocale(WebEngineLibraryInfo::getApplicationLocale()); + ui::ResourceBundle::InitSharedInstanceWithLocale(WebEngineLibraryInfo::getResolvedLocale(), nullptr, ui::ResourceBundle::LOAD_COMMON_RESOURCES); base::CommandLine* parsedCommandLine = base::CommandLine::ForCurrentProcess(); logging::LoggingSettings settings; @@ -172,6 +209,41 @@ void ContentMainDelegateQt::PreSandboxStartup() if (parsedCommandLine->HasSwitch(switches::kSingleProcess)) setlocale(LC_NUMERIC, "C"); #endif + + // from gpu_main.cc: +#if BUILDFLAG(USE_VAAPI) + media::VaapiWrapper::PreSandboxInitialization(); +#endif +#if defined(OS_WIN) + media::DXVAVideoDecodeAccelerator::PreSandboxInitialization(); + media::MediaFoundationVideoEncodeAccelerator::PreSandboxInitialization(); +#endif + +#if defined(OS_MAC) + if (base::FeatureList::IsEnabled(features::kMacV2GPUSandbox)) { + TRACE_EVENT0("gpu", "Initialize VideoToolbox"); + media::InitializeVideoToolbox(); + } +#endif + + if (parsedCommandLine->HasSwitch(service_manager::switches::kApplicationName)) { + std::string appName = parsedCommandLine->GetSwitchValueASCII(service_manager::switches::kApplicationName); + appName = QByteArray::fromPercentEncoding(QByteArray::fromStdString(appName)).toStdString(); + QCoreApplication::setApplicationName(QString::fromStdString(appName)); +#if defined(OS_LINUX) + media::AudioManager::SetGlobalAppName(appName); +#endif + } +} + +void ContentMainDelegateQt::PostEarlyInitialization(bool) +{ + PostFieldTrialInitialization(); +} + +content::ContentClient *ContentMainDelegateQt::CreateContentClient() +{ + return &m_contentClient; } content::ContentBrowserClient *ContentMainDelegateQt::CreateContentBrowserClient() @@ -191,7 +263,7 @@ content::ContentRendererClient *ContentMainDelegateQt::CreateContentRendererClie #if defined(OS_LINUX) base::CommandLine *parsedCommandLine = base::CommandLine::ForCurrentProcess(); std::string process_type = parsedCommandLine->GetSwitchValueASCII(switches::kProcessType); - bool no_sandbox = parsedCommandLine->HasSwitch(service_manager::switches::kNoSandbox); + bool no_sandbox = parsedCommandLine->HasSwitch(sandbox::policy::switches::kNoSandbox); // Reload locale if the renderer process is sandboxed if (process_type == switches::kRendererProcess && !no_sandbox) { @@ -238,8 +310,6 @@ bool ContentMainDelegateQt::BasicStartupComplete(int *exit_code) #if QT_CONFIG(webengine_spellchecker) SafeOverridePath(base::DIR_APP_DICTIONARIES, WebEngineLibraryInfo::getPath(base::DIR_APP_DICTIONARIES)); #endif - if (!content::GetContentClient()) - content::SetContentClient(new ContentClientQt); url::CustomScheme::LoadSchemes(base::CommandLine::ForCurrentProcess()); diff --git a/src/core/content_main_delegate_qt.h b/src/core/content_main_delegate_qt.h index 4d2f33792..170ccc3ca 100644 --- a/src/core/content_main_delegate_qt.h +++ b/src/core/content_main_delegate_qt.h @@ -44,6 +44,7 @@ #include "compositor/content_gpu_client_qt.h" #include "content_browser_client_qt.h" +#include "content_client_qt.h" #include "content_utility_client_qt.h" namespace QtWebEngineCore { @@ -55,7 +56,9 @@ public: // This is where the embedder puts all of its startup code that needs to run // before the sandbox is engaged. void PreSandboxStartup() override; + void PostEarlyInitialization(bool) override; + content::ContentClient *CreateContentClient() override; content::ContentBrowserClient* CreateContentBrowserClient() override; content::ContentGpuClient* CreateContentGpuClient() override; content::ContentRendererClient* CreateContentRendererClient() override; @@ -63,6 +66,7 @@ public: bool BasicStartupComplete(int* /*exit_code*/) override; private: + ContentClientQt m_contentClient; std::unique_ptr<ContentBrowserClientQt> m_browserClient; std::unique_ptr<ContentGpuClientQt> m_gpuClient; std::unique_ptr<ContentUtilityClientQt> m_utilityClient; diff --git a/src/core/content_utility_client_qt.cpp b/src/core/content_utility_client_qt.cpp index 12a538a07..3582e15a7 100644 --- a/src/core/content_utility_client_qt.cpp +++ b/src/core/content_utility_client_qt.cpp @@ -40,6 +40,7 @@ #include "content_utility_client_qt.h" #include "base/no_destructor.h" +#include "mojo/public/cpp/bindings/service_factory.h" #include "services/proxy_resolver/proxy_resolver_factory_impl.h" namespace QtWebEngineCore { @@ -50,12 +51,17 @@ ContentUtilityClientQt::ContentUtilityClientQt() ContentUtilityClientQt::~ContentUtilityClientQt() = default; -void ContentUtilityClientQt::RunIOThreadService(mojo::GenericPendingReceiver *receiver) +auto RunProxyResolver(mojo::PendingReceiver<proxy_resolver::mojom::ProxyResolverFactory> receiver) { - if (auto factory_receiver = receiver->As<proxy_resolver::mojom::ProxyResolverFactory>()) { - static base::NoDestructor<proxy_resolver::ProxyResolverFactoryImpl> factory(std::move(factory_receiver)); - return; - } + return std::make_unique<proxy_resolver::ProxyResolverFactoryImpl>(std::move(receiver)); +} + +mojo::ServiceFactory *ContentUtilityClientQt::GetIOThreadServiceFactory() +{ + static base::NoDestructor<mojo::ServiceFactory> factory { + RunProxyResolver, + }; + return factory.get(); } } // namespace diff --git a/src/core/content_utility_client_qt.h b/src/core/content_utility_client_qt.h index 2a9ecff93..fc1d1eb05 100644 --- a/src/core/content_utility_client_qt.h +++ b/src/core/content_utility_client_qt.h @@ -53,8 +53,7 @@ public: ~ContentUtilityClientQt() override; // content::ContentUtilityClient: - void RunIOThreadService(mojo::GenericPendingReceiver *receiver) override; - + mojo::ServiceFactory *GetIOThreadServiceFactory() override; }; } // namespace diff --git a/src/core/core.pro b/src/core/core.pro index 9709e62c3..fa1d7f6a7 100644 --- a/src/core/core.pro +++ b/src/core/core.pro @@ -1,3 +1,5 @@ +include($$QTWEBENGINE_OUT_ROOT/src/buildtools/qtbuildtools-config.pri) +QT_FOR_CONFIG += buildtools-private TEMPLATE = subdirs # core_headers is a dummy module to syncqt the headers so we can @@ -5,12 +7,14 @@ TEMPLATE = subdirs core_headers.file = core_headers.pro core_api.file = api/core_api.pro +core_lipo.file = core_lipo.pro +core_lipo.depends = gn_run + # This will take the compile output of ninja, and link+deploy the final binary. core_module.file = core_module.pro core_module.depends = core_api +isUniversal(): core_module.depends += core_lipo -# core_generator.pro is a dummy .pro file that is used by qmake -# to generate our main .gyp/BUILD.gn file core_generator.file = core_generator.pro core_generator.depends = core_headers @@ -26,11 +30,25 @@ core_api.depends = gn_run core_project.file = core_project.pro core_project.depends = gn_run -SUBDIRS += \ - core_headers \ - core_generator \ - gn_run \ - core_api \ - core_module - -false: SUBDIRS += core_project +!qtConfig(webengine-core-support):qtConfig(build-qtwebengine-core):!build_pass { + !qtwebengine_makeCheckWebEngineCoreError() { + errorbuild.commands = @echo $$shell_quote("QtWebEngineCore module will not be built. $${skipBuildReason}") + } else { + errorbuild.commands = @echo $$shell_quote("QtWebEngineCore module will not be built for unknown reason, please open a bug report at https://bugreports.qt.io") + } + errorbuild.CONFIG = phony + QMAKE_EXTRA_TARGETS += errorbuild + first.depends += errorbuild + QMAKE_EXTRA_TARGETS += first +} else { + SUBDIRS += \ + core_headers \ + core_generator \ + gn_run \ + core_api \ + core_module + + isUniversal(): SUBDIRS += core_lipo + + false: SUBDIRS += core_project +} diff --git a/src/core/core_chromium.pri b/src/core/core_chromium.pri index 09650d20a..a846f2fbc 100644 --- a/src/core/core_chromium.pri +++ b/src/core/core_chromium.pri @@ -21,9 +21,13 @@ DEFINES += QT_NO_KEYWORDS \ BUILDING_CHROMIUM # Ensure that response files, generated by qtbase/mkspecs/features/moc.prf, are found by moc. -MOC_DIR = $$OUT_PWD/$$getConfigDir()/.moc -RCC_DIR = $$OUT_PWD/$$getConfigDir()/.rcc - +isUniversal() { + MOC_DIR = $$OUT_PWD/$$QT_ARCH/$$getConfigDir()/.moc + RCC_DIR = $$OUT_PWD/$$QT_ARCH/$$getConfigDir()/.rcc +} else { + MOC_DIR = $$OUT_PWD/$$getConfigDir()/.moc + RCC_DIR = $$OUT_PWD/$$getConfigDir()/.rcc +} # Assume that we want mobile touch and low-end hardware behaviors # whenever we are cross compiling. qtConfig(webengine-embedded-build): DEFINES += QTWEBENGINE_EMBEDDED_SWITCHES @@ -50,15 +54,9 @@ SOURCES = \ clipboard_qt.cpp \ color_chooser_qt.cpp \ color_chooser_controller.cpp \ - command_line_pref_store_qt.cpp \ common/qt_ipc_logging.cpp \ common/qt_messages.cpp \ - common/user_script_data.cpp \ - compositor/chromium_gpu_helper.cpp \ - compositor/compositor.cpp \ - compositor/compositor_resource_tracker.cpp \ compositor/content_gpu_client_qt.cpp \ - compositor/delegated_frame_node.cpp \ compositor/display_frame_sink.cpp \ compositor/display_overrides.cpp \ compositor/display_software_output_surface.cpp \ @@ -82,22 +80,16 @@ SOURCES = \ net/client_cert_override.cpp \ net/client_cert_store_data.cpp \ net/cookie_monster_delegate_qt.cpp \ - net/custom_protocol_handler.cpp \ net/custom_url_loader_factory.cpp \ - net/network_delegate_qt.cpp \ net/proxy_config_monitor.cpp \ net/proxy_config_service_qt.cpp \ net/proxying_url_loader_factory_qt.cpp \ net/proxying_restricted_cookie_manager_qt.cpp \ net/qrc_url_scheme_handler.cpp \ - net/restricted_cookie_manager_qt.cpp \ net/ssl_host_state_delegate_qt.cpp \ net/system_network_context_manager.cpp \ - net/url_request_context_getter_qt.cpp \ - net/url_request_custom_job.cpp \ net/url_request_custom_job_delegate.cpp \ net/url_request_custom_job_proxy.cpp \ - net/url_request_notification.cpp \ net/webui_controller_factory_qt.cpp \ ozone/gl_context_qt.cpp \ ozone/gl_ozone_egl_qt.cpp \ @@ -122,14 +114,13 @@ SOURCES = \ renderer/content_renderer_client_qt.cpp \ renderer/content_settings_observer_qt.cpp \ renderer/render_frame_observer_qt.cpp \ - renderer/render_view_observer_qt.cpp \ - renderer/render_thread_observer_qt.cpp \ + renderer/web_engine_page_render_frame.cpp \ + renderer/render_configuration.cpp \ renderer/user_resource_controller.cpp \ - renderer_host/render_view_observer_host_qt.cpp \ + renderer_host/web_engine_page_host.cpp \ renderer_host/user_resource_controller_host.cpp \ resource_bundle_qt.cpp \ resource_context_qt.cpp \ - service/service_qt.cpp \ touch_handle_drawable_qt.cpp \ touch_selection_controller_client_qt.cpp \ touch_selection_menu_controller.cpp \ @@ -162,18 +153,11 @@ HEADERS = \ client_cert_select_controller.h \ clipboard_change_observer.h \ clipboard_qt.h \ - command_line_pref_store_qt.h \ color_chooser_qt.h \ color_chooser_controller_p.h \ color_chooser_controller.h \ common/qt_messages.h \ - common/user_script_data.h \ - compositor/chromium_gpu_helper.h \ - compositor/compositor.h \ - compositor/compositor_resource.h \ - compositor/compositor_resource_tracker.h \ compositor/content_gpu_client_qt.h \ - compositor/delegated_frame_node.h \ compositor/display_frame_sink.h \ compositor/display_software_output_surface.h \ content_client_qt.h \ @@ -192,26 +176,19 @@ HEADERS = \ javascript_dialog_controller_p.h \ javascript_dialog_controller.h \ javascript_dialog_manager_qt.h \ - locked_ptr.h \ login_delegate_qt.h \ media_capture_devices_dispatcher.h \ net/client_cert_override.h \ net/client_cert_store_data.h \ net/cookie_monster_delegate_qt.h \ - net/custom_protocol_handler.h \ net/custom_url_loader_factory.h \ - net/network_delegate_qt.h \ net/proxying_url_loader_factory_qt.h \ net/proxying_restricted_cookie_manager_qt.h \ net/qrc_url_scheme_handler.h \ - net/restricted_cookie_manager_qt.h \ net/ssl_host_state_delegate_qt.h \ net/system_network_context_manager.h \ - net/url_request_context_getter_qt.h \ - net/url_request_custom_job.h \ net/url_request_custom_job_delegate.h \ net/url_request_custom_job_proxy.h \ - net/url_request_notification.h \ net/webui_controller_factory_qt.h \ ozone/gl_context_qt.h \ ozone/gl_ozone_egl_qt.h \ @@ -241,14 +218,13 @@ HEADERS = \ renderer/content_renderer_client_qt.h \ renderer/content_settings_observer_qt.h \ renderer/render_frame_observer_qt.h \ - renderer/render_view_observer_qt.h \ - renderer/render_thread_observer_qt.h \ + renderer/web_engine_page_render_frame.h \ + renderer/render_configuration.h \ renderer/user_resource_controller.h \ - renderer_host/render_view_observer_host_qt.h \ + renderer_host/web_engine_page_host.h \ renderer_host/user_resource_controller_host.h \ request_controller.h \ resource_context_qt.h \ - service/service_qt.h \ touch_handle_drawable_client.h \ touch_handle_drawable_qt.h \ touch_selection_controller_client_qt.h \ @@ -281,14 +257,16 @@ qtConfig(webengine-pepper-plugins) { renderer_host/pepper/pepper_host_factory_qt.cpp \ renderer_host/pepper/pepper_isolated_file_system_message_filter.cpp \ renderer/pepper/pepper_flash_renderer_host_qt.cpp \ - renderer/pepper/pepper_renderer_host_factory_qt.cpp + renderer/pepper/pepper_renderer_host_factory_qt.cpp \ + renderer/plugins/loadable_plugin_placeholder_qt.cpp HEADERS += \ renderer_host/pepper/pepper_flash_browser_host_qt.h \ renderer_host/pepper/pepper_host_factory_qt.h \ renderer_host/pepper/pepper_isolated_file_system_message_filter.h \ renderer/pepper/pepper_flash_renderer_host_qt.h \ - renderer/pepper/pepper_renderer_host_factory_qt.h + renderer/pepper/pepper_renderer_host_factory_qt.h \ + renderer/plugins/loadable_plugin_placeholder_qt.h } qtConfig(webengine-printing-and-pdf) { @@ -314,14 +292,14 @@ contains(QT_CONFIG, opengl) { SOURCES += \ compositor/compositor_resource_fence.cpp \ compositor/display_gl_output_surface.cpp \ - compositor/display_gl_output_surface_qsg.cpp \ - compositor/stream_video_node.cpp \ - compositor/yuv_video_node.cpp + compositor/display_gl_output_surface_qsg.cpp HEADERS += \ compositor/compositor_resource_fence.h \ - compositor/display_gl_output_surface.h \ - compositor/stream_video_node.h \ - compositor/yuv_video_node.h + compositor/display_gl_output_surface.h + macos { + HEADERS+=macos_context_type_helper.h + SOURCES+=macos_context_type_helper.mm + } } qtConfig(webengine-geolocation) { @@ -342,33 +320,39 @@ qtConfig(webengine-extensions) { common/extensions/extensions_api_provider_qt.cpp \ common/extensions/extensions_client_qt.cpp \ extensions/component_extension_resource_manager_qt.cpp \ + extensions/extension_host_delegate_qt.cpp \ extensions/extension_system_qt.cpp \ extensions/extension_system_factory_qt.cpp \ extensions/extension_web_contents_observer_qt.cpp \ extensions/extensions_api_client_qt.cpp \ - extensions/extensions_browser_api_provider_qt.cpp \ extensions/extensions_browser_client_qt.cpp \ + extensions/messaging_delegate_qt.cpp \ extensions/mime_handler_view_guest_delegate_qt.cpp \ + extensions/pdf_iframe_navigation_throttle_qt.cpp \ + extensions/plugin_service_filter_qt.cpp \ + net/plugin_response_interceptor_url_loader_throttle.cpp \ renderer/extensions/extensions_dispatcher_delegate_qt.cpp \ renderer/extensions/extensions_renderer_client_qt.cpp \ renderer/extensions/renderer_permissions_policy_delegate_qt.cpp \ - renderer/extensions/resource_request_policy_qt.cpp \ - renderer_host/resource_dispatcher_host_delegate_qt.cpp + renderer/extensions/resource_request_policy_qt.cpp HEADERS += \ common/extensions/extensions_api_provider_qt.h \ common/extensions/extensions_client_qt.h \ extensions/component_extension_resource_manager_qt.h \ + extensions/extension_host_delegate_qt.h \ extensions/extension_system_qt.h \ extensions/extension_system_factory_qt.h \ extensions/extension_web_contents_observer_qt.h \ extensions/extensions_api_client_qt.h \ - extensions/extensions_browser_api_provider_qt.h \ extensions/extensions_browser_client_qt.h \ + extensions/messaging_delegate_qt.h \ extensions/mime_handler_view_guest_delegate_qt.h \ + extensions/pdf_iframe_navigation_throttle_qt.h \ + extensions/plugin_service_filter_qt.h \ + net/plugin_response_interceptor_url_loader_throttle.h \ renderer/extensions/extensions_dispatcher_delegate_qt.h \ renderer/extensions/extensions_renderer_client_qt.h \ renderer/extensions/renderer_permissions_policy_delegate_qt.h \ - renderer/extensions/resource_request_policy_qt.h \ - renderer_host/resource_dispatcher_host_delegate_qt.h + renderer/extensions/resource_request_policy_qt.h } diff --git a/src/core/core_gn_config.pri b/src/core/core_gn_config.pri index a089eecd0..379bbac94 100644 --- a/src/core/core_gn_config.pri +++ b/src/core/core_gn_config.pri @@ -1,16 +1,23 @@ CONFIG = gn_generator $$CONFIG GN_SRC_DIR = $$PWD -GN_FILE = $$OUT_PWD/$$getConfigDir()/BUILD.gn +isUniversal() { + for(arch, QT_ARCHS) { + GN_FILES += $$OUT_PWD/$$arch/$$getConfigDir()/BUILD.gn + } +} else { + GN_FILES = $$OUT_PWD/$$getConfigDir()/BUILD.gn +} GN_FIND_MOCABLES_SCRIPT = $$shell_path($$QTWEBENGINE_ROOT/tools/scripts/gn_find_mocables.py) GN_RUN_BINARY_SCRIPT = $$shell_path($$QTWEBENGINE_ROOT/tools/scripts/gn_run_binary.py) GN_IMPORTS = $$PWD/qtwebengine.gni -qtConfig (webengine-extensions) { +qtConfig(webengine-extensions) { GN_INCLUDES += $$PWD/qtwebengine_sources.gni $$PWD/qtwebengine_resources.gni $$PWD/common/extensions/api/qtwebengine_extensions_features.gni } else { GN_INCLUDES = $$PWD/qtwebengine_sources.gni $$PWD/qtwebengine_resources.gni } GN_CORE_INCLUDE_DIRS = $$PWD/service GN_CREATE_PRI = true +GN_PRECOMPILED_HEADERS = true QMAKE_INTERNAL_INCLUDED_FILES = $$GN_IMPORTS $$GN_INCLUDES $$GN_FILE diff --git a/src/core/core_lipo.pro b/src/core/core_lipo.pro new file mode 100644 index 000000000..41846b7f2 --- /dev/null +++ b/src/core/core_lipo.pro @@ -0,0 +1,9 @@ +TEMPLATE = aux + +qtConfig(debug_and_release): CONFIG += debug_and_release +qtConfig(build_all): CONFIG += build_all + +TARGET= QtWebEngineCore +include($${QTWEBENGINE_ROOT}/src/buildtools/config/lipo.pri) + + diff --git a/src/core/core_module.pro b/src/core/core_module.pro index 4b9268e1a..9e087c815 100644 --- a/src/core/core_module.pro +++ b/src/core/core_module.pro @@ -1,63 +1,14 @@ MODULE = webenginecore include(core_common.pri) -# Needed to set a CFBundleIdentifier -QMAKE_INFO_PLIST = Info_mac.plist - -linking_pri = $$OUT_PWD/$$getConfigDir()/$${TARGET}.pri - -!include($$linking_pri) { - error("Could not find the linking information that gn should have generated.") +isUniversal() { + include($${QTWEBENGINE_ROOT}/src/buildtools/config/lipo_linking.pri) +} else { + include($${QTWEBENGINE_ROOT}/src/buildtools/config/linking.pri) } api_library_name = qtwebenginecoreapi$$qtPlatformTargetSuffix() api_library_path = $$OUT_PWD/api/$$getConfigDir() - -# Do not precompile any headers. We are only interested in the linker step. -PRECOMPILED_HEADER = - -isEmpty(NINJA_OBJECTS): error("Missing object files from QtWebEngineCore linking pri.") -isEmpty(NINJA_LFLAGS): error("Missing linker flags from QtWebEngineCore linking pri") -isEmpty(NINJA_ARCHIVES): error("Missing archive files from QtWebEngineCore linking pri") -isEmpty(NINJA_LIBS): error("Missing library files from QtWebEngineCore linking pri") -NINJA_OBJECTS = $$eval($$list($$NINJA_OBJECTS)) -# Do manual response file linking for macOS and Linux - -RSP_OBJECT_FILE = $$OUT_PWD/$$getConfigDir()/$${TARGET}_o.rsp -for(object, NINJA_OBJECTS): RSP_O_CONTENT += $$object -write_file($$RSP_OBJECT_FILE, RSP_O_CONTENT) -RSP_ARCHIVE_FILE = $$OUT_PWD/$$getConfigDir()/$${TARGET}_a.rsp -for(archive, NINJA_ARCHIVES): RSP_A_CONTENT += $$archive -write_file($$RSP_ARCHIVE_FILE, RSP_A_CONTENT) -macos:LIBS_PRIVATE += -Wl,-filelist,$$shell_quote($$RSP_OBJECT_FILE) -linux:QMAKE_LFLAGS += @$${RSP_OBJECT_FILE} -# QTBUG-58710 add main rsp file on windows -win32:QMAKE_LFLAGS += @$${RSP_OBJECT_FILE} -linux:QMAKE_LFLAGS += -Wl,--start-group @$${RSP_ARCHIVE_FILE} -Wl,--end-group -else: LIBS_PRIVATE += $$NINJA_ARCHIVES -LIBS_PRIVATE += $$NINJA_LIB_DIRS $$NINJA_LIBS -# GN's LFLAGS doesn't always work across all the Linux configurations we support. -# The Windows and macOS ones from GN does provide a few useful flags however - -unix:qtConfig(webengine-noexecstack): \ - QMAKE_LFLAGS += -Wl,-z,noexecstack -linux { - # add chromium flags - for(flag, NINJA_LFLAGS) { - # filter out some flags - !contains(flag, .*noexecstack$): \ - !contains(flag, .*as-needed$): \ - !contains(flag, ^-B.*): \ - !contains(flag, ^-fuse-ld.*): \ - QMAKE_LFLAGS += $$flag - } -} else { - QMAKE_LFLAGS += $$NINJA_LFLAGS -} - -POST_TARGETDEPS += $$NINJA_TARGETDEPS - - LIBS_PRIVATE += -L$$api_library_path CONFIG *= no_smart_library_merge osx { @@ -87,13 +38,26 @@ win32 { POST_TARGETDEPS += $${api_library_path}$${QMAKE_DIR_SEP}lib$${api_library_name}.a } +# Needed to set a CFBundleIdentifier +QMAKE_INFO_PLIST = Info_mac.plist + # Using -Wl,-Bsymbolic-functions seems to confuse the dynamic linker # and doesn't let Chromium get access to libc symbols through dlsym. CONFIG -= bsymbolic_functions -linux:qtConfig(separate_debug_info): QMAKE_POST_LINK="cd $(DESTDIR) && $(STRIP) --strip-unneeded $(TARGET)" +linux { + !ccache:!use_gold_linker:!use_lld_linker { + QMAKE_LINK="ulimit -n 4096 && $$QMAKE_LINK" + QMAKE_LINK_SHLIB="ulimit -n 4096 && $$QMAKE_LINK_SHLIB" + } + qtConfig(separate_debug_info): QMAKE_POST_LINK="cd $(DESTDIR) && $(STRIP) --strip-unneeded $(TARGET)" +} -REPACK_DIR = $$OUT_PWD/$$getConfigDir() +isUniversal() { + REPACK_DIR = $$OUT_PWD/$$QT_ARCH/$$getConfigDir() +} else { + REPACK_DIR = $$OUT_PWD/$$getConfigDir() +} # Duplicated from resources/resources.gyp LOCALE_LIST = am ar bg bn ca cs da de el en-GB en-US es-419 es et fa fi fil fr gu he hi hr hu id it ja kn ko lt lv ml mr ms nb nl pl pt-BR pt-PT ro ru sk sl sr sv sw ta te th tr uk vi zh-CN zh-TW @@ -105,9 +69,9 @@ resources.files = $$REPACK_DIR/qtwebengine_resources.pak \ $$REPACK_DIR/qtwebengine_resources_200p.pak \ $$REPACK_DIR/qtwebengine_devtools_resources.pak -icu.files = $$OUT_PWD/$$getConfigDir()/icudtl.dat +icu.files = $$REPACK_DIR/icudtl.dat -!debug_and_release|!build_all|CONFIG(release, debug|release) { +!qtConfig(debug_and_release)|!qtConfig(build_all)|CONFIG(release, debug|release) { qtConfig(framework) { locales.version = Versions locales.path = Resources/qtwebengine_locales @@ -146,7 +110,7 @@ icu.files = $$OUT_PWD/$$getConfigDir()/icudtl.dat } } -!build_pass:debug_and_release { +!build_pass:qtConfig(debug_and_release) { # Special GNU make target that ensures linking isn't done for both debug and release builds # at the same time. notParallel.target = .NOTPARALLEL diff --git a/src/core/delegated_frame_host_client_qt.cpp b/src/core/delegated_frame_host_client_qt.cpp index 817ea2fa5..8a3601ada 100644 --- a/src/core/delegated_frame_host_client_qt.cpp +++ b/src/core/delegated_frame_host_client_qt.cpp @@ -58,12 +58,6 @@ SkColor DelegatedFrameHostClientQt::DelegatedFrameHostGetGutterColor() const return p->GetBackgroundColor().value_or(SK_ColorWHITE); } -void DelegatedFrameHostClientQt::OnBeginFrame(base::TimeTicks frame_time) -{ - p->host()->ProgressFlingIfNeeded(frame_time); - p->UpdateNeedsBeginFramesInternal(); -} - void DelegatedFrameHostClientQt::OnFrameTokenChanged(uint32_t frame_token) { p->OnFrameTokenChangedForView(frame_token); diff --git a/src/core/delegated_frame_host_client_qt.h b/src/core/delegated_frame_host_client_qt.h index b5dc6eb59..1f5a9858b 100644 --- a/src/core/delegated_frame_host_client_qt.h +++ b/src/core/delegated_frame_host_client_qt.h @@ -57,7 +57,6 @@ public: ui::Layer *DelegatedFrameHostGetLayer() const override; bool DelegatedFrameHostIsVisible() const override; SkColor DelegatedFrameHostGetGutterColor() const override; - void OnBeginFrame(base::TimeTicks frame_time) override; void OnFrameTokenChanged(uint32_t frame_token) override; float GetDeviceScaleFactor() const override; void InvalidateLocalSurfaceIdOnEviction() override; diff --git a/src/core/desktop_screen_qt.cpp b/src/core/desktop_screen_qt.cpp index 15a3856fc..fd7a2c54f 100644 --- a/src/core/desktop_screen_qt.cpp +++ b/src/core/desktop_screen_qt.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWebEngine module of the Qt Toolkit. @@ -40,74 +40,101 @@ #include "desktop_screen_qt.h" #include "ui/display/display.h" -#include "ui/gfx/geometry/point.h" -#include <QtGlobal> +#include "type_conversion.h" -namespace QtWebEngineCore { - -gfx::Point DesktopScreenQt::GetCursorScreenPoint() -{ - Q_UNREACHABLE(); - return gfx::Point(); -} - -bool DesktopScreenQt::IsWindowUnderCursor(gfx::NativeWindow) -{ - Q_UNREACHABLE(); - return false; -} +#include <QGuiApplication> +#include <QScreen> -gfx::NativeWindow DesktopScreenQt::GetWindowAtScreenPoint(const gfx::Point& point) -{ - Q_UNREACHABLE(); - return gfx::NativeWindow(); -} +#include <cmath> -int DesktopScreenQt::GetNumDisplays() const -{ - Q_UNREACHABLE(); - return 0; -} +namespace QtWebEngineCore { -std::vector<display::Display>& DesktopScreenQt::GetAllDisplays() const +static display::Display::Rotation toDisplayRotation(Qt::ScreenOrientation orientation) { - static std::vector<display::Display> empty; - return empty; + switch (orientation) { + case Qt::PrimaryOrientation: + case Qt::LandscapeOrientation: + return display::Display::ROTATE_0; + case Qt::PortraitOrientation: + return display::Display::ROTATE_90; + case Qt::InvertedLandscapeOrientation: + return display::Display::ROTATE_180; + case Qt::InvertedPortraitOrientation: + return display::Display::ROTATE_270; + } } -display::Display DesktopScreenQt::GetDisplayNearestWindow(gfx::NativeWindow window) const +display::Display toDisplayDisplay(int id, const QScreen *screen) { - // RenderViewHostImpl::OnStartDragging uses this to determine - // the scale factor for the view. - return display::Display(0); + auto display = display::Display(id, toGfx(screen->geometry())); + display.set_work_area(toGfx(screen->availableGeometry())); + display.set_device_scale_factor(screen->devicePixelRatio()); + display.set_is_monochrome(screen->depth() == 1); + display.set_color_depth(screen->depth()); + display.set_depth_per_component(8); // FIXME: find the real value + display.set_display_frequency(std::ceil(screen->refreshRate())); + display.set_rotation(toDisplayRotation(screen->orientation())); + if (screen->nativeOrientation() != Qt::PrimaryOrientation) + display.set_panel_rotation(toDisplayRotation(screen->nativeOrientation())); + return display; } -display::Display DesktopScreenQt::GetDisplayNearestPoint(const gfx::Point& point) const +DesktopScreenQt::DesktopScreenQt() { - Q_UNREACHABLE(); - return display::Display(); + initializeScreens(); } -display::Display DesktopScreenQt::GetDisplayMatching(const gfx::Rect& match_rect) const +DesktopScreenQt::~DesktopScreenQt() { - Q_UNREACHABLE(); - return display::Display(); + for (auto conn : qAsConst(m_connections)) + QObject::disconnect(conn); } -display::Display DesktopScreenQt::GetPrimaryDisplay() const +void DesktopScreenQt::initializeScreens() { - return display::Display(0); + if (updateAllScreens()) { + m_connections[0] = + QObject::connect(qApp, &QGuiApplication::primaryScreenChanged, [this] (QScreen *screen) { + ProcessDisplayChanged(toDisplayDisplay(0, screen), true /* is_primary */); + }); + // no guarantees how these will affect ids: + m_connections[1] = + QObject::connect(qApp, &QGuiApplication::screenAdded, [this] (QScreen *) { + updateAllScreens(); + }); + m_connections[2] = + QObject::connect(qApp, &QGuiApplication::screenRemoved, [this] (QScreen *) { + updateAllScreens(); + }); + } else { + // Running headless + ProcessDisplayChanged(display::Display::GetDefaultDisplay(), true /* is_primary */); + m_connections[0] = + QObject::connect(qApp, &QGuiApplication::screenAdded, [this] (QScreen *) { + display_list().RemoveDisplay(display::kDefaultDisplayId); + QObject::disconnect(m_connections[0]); + initializeScreens(); + }); + } } -void DesktopScreenQt::AddObserver(display::DisplayObserver* observer) +bool DesktopScreenQt::updateAllScreens() { - Q_UNREACHABLE(); + Q_ASSERT(qApp->primaryScreen() == qApp->screens().first()); + const auto screens = qApp->screens(); + const int oldLen = GetNumDisplays(); + for (int i = screens.length(); i < oldLen; ++i) + display_list().RemoveDisplay(i); + for (int i = 0; i < screens.length(); ++i) + ProcessDisplayChanged(toDisplayDisplay(i, screens.at(i)), i == 0 /* is_primary */); + + return screens.length() > 0; } -void DesktopScreenQt::RemoveObserver(display::DisplayObserver* observer) +display::Display DesktopScreenQt::GetDisplayNearestWindow(gfx::NativeWindow /*window*/) const { - Q_UNREACHABLE(); + return GetPrimaryDisplay(); } } // namespace QtWebEngineCore diff --git a/src/core/desktop_screen_qt.h b/src/core/desktop_screen_qt.h index 0c52c615a..1b2e095a4 100644 --- a/src/core/desktop_screen_qt.h +++ b/src/core/desktop_screen_qt.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWebEngine module of the Qt Toolkit. @@ -40,24 +40,24 @@ #ifndef DESKTOP_SCREEN_QT_H #define DESKTOP_SCREEN_QT_H -#include "ui/display/screen.h" +#include "ui/display/screen_base.h" + +#include <qmetaobject.h> namespace QtWebEngineCore { -class DesktopScreenQt : public display::Screen { +class DesktopScreenQt : public display::ScreenBase +{ public: - // Overridden from gfx::Screen: - gfx::Point GetCursorScreenPoint() override; - bool IsWindowUnderCursor(gfx::NativeWindow) override; - gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point) override; - int GetNumDisplays() const override; - std::vector<display::Display>& GetAllDisplays() const override; - display::Display GetDisplayNearestWindow(gfx::NativeWindow window) const override; - display::Display GetDisplayNearestPoint(const gfx::Point& point) const override; - display::Display GetDisplayMatching(const gfx::Rect& match_rect) const override; - display::Display GetPrimaryDisplay() const override; - void AddObserver(display::DisplayObserver* observer) override; - void RemoveObserver(display::DisplayObserver* observer) override; + DesktopScreenQt(); + ~DesktopScreenQt() override; + + display::Display GetDisplayNearestWindow(gfx::NativeWindow /*window*/) const override; + +private: + void initializeScreens(); + bool updateAllScreens(); + QMetaObject::Connection m_connections[3]; }; } // namespace QtWebEngineCore diff --git a/src/core/devtools_frontend_qt.cpp b/src/core/devtools_frontend_qt.cpp index 1dcbd1e9d..440c52d33 100644 --- a/src/core/devtools_frontend_qt.cpp +++ b/src/core/devtools_frontend_qt.cpp @@ -59,20 +59,24 @@ #include "base/strings/utf_string_conversions.h" #include "base/task/post_task.h" #include "base/values.h" +#include "chrome/browser/devtools/devtools_eye_dropper.h" #include "chrome/common/url_constants.h" #include "components/prefs/in_memory_pref_store.h" #include "components/prefs/json_pref_store.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/file_url_loader.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_view_host.h" +#include "content/public/browser/shared_cors_origin_access_list.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_client.h" #include "content/public/common/url_constants.h" +#include "content/public/common/url_utils.h" #include "ipc/ipc_channel.h" #include "net/http/http_response_headers.h" #include "net/traffic_annotation/network_traffic_annotation.h" @@ -83,10 +87,21 @@ using namespace QtWebEngineCore; namespace { -std::unique_ptr<base::DictionaryValue> BuildObjectForResponse(const net::HttpResponseHeaders *rh) +std::unique_ptr<base::DictionaryValue> BuildObjectForResponse(const net::HttpResponseHeaders *rh, + bool success, + int net_error) { auto response = std::make_unique<base::DictionaryValue>(); - response->SetInteger("statusCode", rh ? rh->response_code() : 200); + int responseCode = 200; + if (rh) { + responseCode = rh->response_code(); + } else if (!success) { + // In case of no headers, assume file:// URL and failed to load + responseCode = 404; + } + response->SetInteger("statusCode", responseCode); + response->SetInteger("netError", net_error); + response->SetString("netErrorName", net::ErrorToString(net_error)); auto headers = std::make_unique<base::DictionaryValue>(); size_t iterator = 0; @@ -103,7 +118,7 @@ std::unique_ptr<base::DictionaryValue> BuildObjectForResponse(const net::HttpRes static std::string GetFrontendURL() { - return "devtools://devtools/bundled/devtools_app.html"; + return "devtools://devtools/bundled/inspector.html"; } } // namespace @@ -130,7 +145,7 @@ public: private: void OnResponseStarted(const GURL &final_url, - const network::ResourceResponseHead &response_head) + const network::mojom::URLResponseHead &response_head) { response_headers_ = response_head.headers; } @@ -156,8 +171,7 @@ private: void OnComplete(bool success) override { - Q_UNUSED(success); - auto response = BuildObjectForResponse(response_headers_.get()); + auto response = BuildObjectForResponse(response_headers_.get(), success, loader_->NetError()); bindings_->SendMessageAck(request_id_, response.get()); bindings_->m_loaders.erase(bindings_->m_loaders.find(this)); } @@ -213,7 +227,9 @@ DevToolsFrontendQt *DevToolsFrontendQt::Show(QSharedPointer<WebContentsAdapter> DevToolsFrontendQt::DevToolsFrontendQt(QSharedPointer<WebContentsAdapter> webContentsAdapter, content::WebContents *inspectedContents) : content::WebContentsObserver(webContentsAdapter->webContents()) - , m_webContentsAdapter(webContentsAdapter) + , m_frontendAdapter(webContentsAdapter) + , m_inspectedAdapter(static_cast<WebContentsDelegateQt *>(inspectedContents->GetDelegate()) + ->webContentsAdapter()) , m_inspectedContents(inspectedContents) , m_inspect_element_at_x(-1) , m_inspect_element_at_y(-1) @@ -233,7 +249,7 @@ DevToolsFrontendQt::DevToolsFrontendQt(QSharedPointer<WebContentsAdapter> webCon DevToolsFrontendQt::~DevToolsFrontendQt() { - if (QSharedPointer<WebContentsAdapter> p = m_webContentsAdapter) + if (QSharedPointer<WebContentsAdapter> p = m_frontendAdapter) p->setInspector(false); } @@ -312,8 +328,8 @@ void DevToolsFrontendQt::DocumentAvailableInMainFrame() void DevToolsFrontendQt::WebContentsDestroyed() { - if (m_inspectedContents) - static_cast<WebContentsDelegateQt *>(m_inspectedContents->GetDelegate())->webContentsAdapter()->devToolsFrontendDestroyed(this); + if (m_inspectedAdapter) + m_inspectedAdapter->devToolsFrontendDestroyed(this); if (m_agentHost) { m_agentHost->DetachClient(this); @@ -336,7 +352,8 @@ void DevToolsFrontendQt::RemovePreference(const std::string &name) void DevToolsFrontendQt::ClearPreferences() { - if (web_contents()->GetBrowserContext()->IsOffTheRecord()) + ProfileQt *profile = static_cast<ProfileQt *>(web_contents()->GetBrowserContext()); + if (profile->IsOffTheRecord() || profile->profileAdapter()->storageName().isEmpty()) m_prefStore = scoped_refptr<PersistentPrefStore>(new InMemoryPrefStore()); else CreateJsonPreferences(true); @@ -373,7 +390,7 @@ void DevToolsFrontendQt::HandleMessageFromDevToolsFrontend(const std::string &me std::string protocol_message; if (!params->GetString(0, &protocol_message)) return; - m_agentHost->DispatchProtocolMessage(this, protocol_message); + m_agentHost->DispatchProtocolMessage(this, base::as_bytes(base::make_span(protocol_message))); } else if (method == "loadCompleted") { web_contents()->GetMainFrame()->ExecuteJavaScript(base::ASCIIToUTF16("DevToolsAPI.setUseSoftMenu(true);"), base::NullCallback()); @@ -389,6 +406,7 @@ void DevToolsFrontendQt::HandleMessageFromDevToolsFrontend(const std::string &me if (!gurl.is_valid()) { base::DictionaryValue response; response.SetInteger("statusCode", 404); + response.SetBoolean("urlValid", false); SendMessageAck(request_id, &response); return; } @@ -422,18 +440,31 @@ void DevToolsFrontendQt::HandleMessageFromDevToolsFrontend(const std::string &me resource_request->url = gurl; // TODO(caseq): this preserves behavior of URLFetcher-based implementation. // We really need to pass proper first party origin from the front-end. - resource_request->site_for_cookies = gurl; + resource_request->site_for_cookies = net::SiteForCookies::FromUrl(gurl); resource_request->headers.AddHeadersFromString(headers); - auto *partition = content::BrowserContext::GetStoragePartitionForSite( - web_contents()->GetBrowserContext(), gurl); - auto factory = partition->GetURLLoaderFactoryForBrowserProcess(); - + mojo::Remote<network::mojom::URLLoaderFactory> file_url_loader_factory; + scoped_refptr<network::SharedURLLoaderFactory> network_url_loader_factory; + network::mojom::URLLoaderFactory *url_loader_factory; + if (gurl.SchemeIsFile()) { + file_url_loader_factory.Bind(content::CreateFileURLLoaderFactory(base::FilePath(), nullptr)); + url_loader_factory = file_url_loader_factory.get(); + } else if (content::HasWebUIScheme(gurl)) { + base::DictionaryValue response; + response.SetInteger("statusCode", 403); + SendMessageAck(request_id, &response); + return; + } else { + auto *partition = content::BrowserContext::GetStoragePartitionForSite( + web_contents()->GetBrowserContext(), gurl); + network_url_loader_factory = partition->GetURLLoaderFactoryForBrowserProcess(); + url_loader_factory = network_url_loader_factory.get(); + } auto simple_url_loader = network::SimpleURLLoader::Create( std::move(resource_request), traffic_annotation); auto resource_loader = std::make_unique<NetworkResourceLoader>( stream_id, request_id, this, std::move(simple_url_loader), - factory.get()); + url_loader_factory); m_loaders.insert(std::move(resource_loader)); return; } else if (method == "getPreferences") { @@ -459,6 +490,22 @@ void DevToolsFrontendQt::HandleMessageFromDevToolsFrontend(const std::string &me } else if (method == "reattach") { m_agentHost->DetachClient(this); m_agentHost->AttachClient(this); + } else if (method == "inspectedURLChanged" && params && params->GetSize() >= 1) { + std::string url; + if (!params->GetString(0, &url)) + return; + const std::string kHttpPrefix = "http://"; + const std::string kHttpsPrefix = "https://"; + const std::string simplified_url = + base::StartsWith(url, kHttpsPrefix, base::CompareCase::SENSITIVE) + ? url.substr(kHttpsPrefix.length()) + : base::StartsWith(url, kHttpPrefix, base::CompareCase::SENSITIVE) + ? url.substr(kHttpPrefix.length()) + : url; + // DevTools UI is not localized. + web_contents()->UpdateTitleForEntry(web_contents()->GetController().GetActiveEntry(), + base::UTF8ToUTF16( + base::StringPrintf("DevTools - %s", simplified_url.c_str()))); } else if (method == "openInNewTab") { std::string urlString; if (!params->GetString(0, &urlString)) @@ -483,6 +530,13 @@ void DevToolsFrontendQt::HandleMessageFromDevToolsFrontend(const std::string &me return; } else if (method == "bringToFront") { Activate(); + } else if (method == "closeWindow") { + web_contents()->Close(); + } else if (method == "setEyeDropperActive" && params->GetSize() == 1) { + bool active; + if (!params->GetBoolean(0, &active)) + return; + SetEyeDropperActive(active); } else { VLOG(1) << "Unimplemented devtools method: " << message; return; @@ -492,22 +546,47 @@ void DevToolsFrontendQt::HandleMessageFromDevToolsFrontend(const std::string &me SendMessageAck(request_id, nullptr); } -void DevToolsFrontendQt::DispatchProtocolMessage(content::DevToolsAgentHost *agentHost, const std::string &message) +void DevToolsFrontendQt::SetEyeDropperActive(bool active) +{ + if (!m_inspectedContents) + return; + if (active) { + m_eyeDropper.reset(new DevToolsEyeDropper( + m_inspectedContents, + base::Bind(&DevToolsFrontendQt::ColorPickedInEyeDropper, + base::Unretained(this)))); + } else { + m_eyeDropper.reset(); + } +} + +void DevToolsFrontendQt::ColorPickedInEyeDropper(int r, int g, int b, int a) +{ + base::DictionaryValue color; + color.SetInteger("r", r); + color.SetInteger("g", g); + color.SetInteger("b", b); + color.SetInteger("a", a); + CallClientFunction("DevToolsAPI.eyeDropperPickedColor", &color, nullptr, nullptr); +} + +void DevToolsFrontendQt::DispatchProtocolMessage(content::DevToolsAgentHost *agentHost, base::span<const uint8_t> message) { Q_UNUSED(agentHost); - if (message.length() < kMaxMessageChunkSize) { + base::StringPiece message_sp(reinterpret_cast<const char*>(message.data()), message.size()); + if (message_sp.length() < kMaxMessageChunkSize) { std::string param; - base::EscapeJSONString(message, true, ¶m); + base::EscapeJSONString(message_sp, true, ¶m); std::string code = "DevToolsAPI.dispatchMessage(" + param + ");"; base::string16 javascript = base::UTF8ToUTF16(code); web_contents()->GetMainFrame()->ExecuteJavaScript(javascript, base::NullCallback()); return; } - size_t total_size = message.length(); - for (size_t pos = 0; pos < message.length(); pos += kMaxMessageChunkSize) { + size_t total_size = message_sp.length(); + for (size_t pos = 0; pos < message_sp.length(); pos += kMaxMessageChunkSize) { std::string param; - base::EscapeJSONString(message.substr(pos, kMaxMessageChunkSize), true, ¶m); + base::EscapeJSONString(message_sp.substr(pos, kMaxMessageChunkSize), true, ¶m); std::string code = "DevToolsAPI.dispatchMessageChunk(" + param + "," + std::to_string(pos ? 0 : total_size) + ");"; base::string16 javascript = base::UTF8ToUTF16(code); @@ -549,6 +628,7 @@ void DevToolsFrontendQt::AgentHostClosed(content::DevToolsAgentHost *agentHost) DCHECK(agentHost == m_agentHost.get()); m_agentHost = nullptr; m_inspectedContents = nullptr; + m_inspectedAdapter = nullptr; Close(); } diff --git a/src/core/devtools_frontend_qt.h b/src/core/devtools_frontend_qt.h index fed2d47fc..aac5909dc 100644 --- a/src/core/devtools_frontend_qt.h +++ b/src/core/devtools_frontend_qt.h @@ -65,6 +65,7 @@ class RenderViewHost; class WebContents; } // namespace content +class DevToolsEyeDropper; class PersistentPrefStore; namespace QtWebEngineCore { @@ -97,7 +98,7 @@ protected: // content::DevToolsAgentHostClient implementation. void AgentHostClosed(content::DevToolsAgentHost* agent_host) override; - void DispatchProtocolMessage(content::DevToolsAgentHost* agent_host, const std::string& message) override; + void DispatchProtocolMessage(content::DevToolsAgentHost* agent_host, base::span<const uint8_t> message) override; void SetPreferences(const std::string& json); virtual void HandleMessageFromDevToolsFrontend(const std::string& message); @@ -113,15 +114,19 @@ private: void RemovePreference(const std::string &name); void ClearPreferences(); void CreateJsonPreferences(bool clear); + void SetEyeDropperActive(bool active); + void ColorPickedInEyeDropper(int r, int g, int b, int a); // We shouldn't be keeping it alive - QWeakPointer<WebContentsAdapter> m_webContentsAdapter; + QWeakPointer<WebContentsAdapter> m_frontendAdapter; + WebContentsAdapter *m_inspectedAdapter; WebContentsDelegateQt *m_frontendDelegate; content::WebContents *m_inspectedContents; scoped_refptr<content::DevToolsAgentHost> m_agentHost; int m_inspect_element_at_x; int m_inspect_element_at_y; std::unique_ptr<content::DevToolsFrontendHost> m_frontendHost; + std::unique_ptr<DevToolsEyeDropper> m_eyeDropper; class NetworkResourceLoader; std::set<std::unique_ptr<NetworkResourceLoader>, base::UniquePtrComparator> m_loaders; diff --git a/src/core/devtools_manager_delegate_qt.cpp b/src/core/devtools_manager_delegate_qt.cpp index ecd2a7d40..51f00d3e5 100644 --- a/src/core/devtools_manager_delegate_qt.cpp +++ b/src/core/devtools_manager_delegate_qt.cpp @@ -114,7 +114,7 @@ DevToolsServerQt::~DevToolsServerQt() void DevToolsServerQt::parseAddressAndPort() { - const QString inspectorEnv = QString::fromUtf8(qgetenv("QTWEBENGINE_REMOTE_DEBUGGING")); + const QString inspectorEnv = qEnvironmentVariable("QTWEBENGINE_REMOTE_DEBUGGING"); const base::CommandLine &commandLine = *base::CommandLine::ForCurrentProcess(); QString portStr; @@ -181,7 +181,7 @@ void DevToolsManagerDelegateQt::Initialized(const net::IPEndPoint *ip_address) std::string DevToolsManagerDelegateQt::GetDiscoveryPageHTML() { - return ui::ResourceBundle::GetSharedInstance().GetRawDataResource(IDR_DEVTOOLS_DISCOVERY_PAGE_HTML).as_string(); + return ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(IDR_DEVTOOLS_DISCOVERY_PAGE_HTML); } bool DevToolsManagerDelegateQt::HasBundledFrontendResources() diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp index 7049b8273..b694d1759 100644 --- a/src/core/download_manager_delegate_qt.cpp +++ b/src/core/download_manager_delegate_qt.cpp @@ -77,9 +77,9 @@ DownloadManagerDelegateQt::~DownloadManagerDelegateQt() { } -void DownloadManagerDelegateQt::GetNextId(const content::DownloadIdCallback& callback) +void DownloadManagerDelegateQt::GetNextId(content::DownloadIdCallback callback) { - callback.Run(m_currentId); + std::move(callback).Run(m_currentId); } download::DownloadItem *DownloadManagerDelegateQt::findDownloadById(quint32 downloadId) @@ -88,13 +88,15 @@ download::DownloadItem *DownloadManagerDelegateQt::findDownloadById(quint32 down return dlm->GetDownload(downloadId); } -void DownloadManagerDelegateQt::cancelDownload(const content::DownloadTargetCallback& callback) +void DownloadManagerDelegateQt::cancelDownload(content::DownloadTargetCallback callback) { - callback.Run(base::FilePath(), - download::DownloadItem::TARGET_DISPOSITION_PROMPT, - download::DownloadDangerType::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, - base::FilePath(), - download::DownloadInterruptReason::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED); + std::move(callback).Run(base::FilePath(), + download::DownloadItem::TARGET_DISPOSITION_PROMPT, + download::DownloadDangerType::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, + download::DownloadItem::UNKNOWN, + base::FilePath(), + base::nullopt, + download::DownloadInterruptReason::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED); } void DownloadManagerDelegateQt::cancelDownload(quint32 downloadId) @@ -121,8 +123,8 @@ void DownloadManagerDelegateQt::removeDownload(quint32 downloadId) download->Remove(); } -bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem* item, - const content::DownloadTargetCallback& callback) +bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem *item, + content::DownloadTargetCallback *callback) { m_currentId = item->GetId(); @@ -130,8 +132,12 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem* // will already return that the file exists. Forced file paths seem to be only used for // store downloads and other special downloads, so they might never end up here anyway. if (!item->GetForcedFilePath().empty()) { - callback.Run(item->GetForcedFilePath(), download::DownloadItem::TARGET_DISPOSITION_PROMPT, - download::DownloadDangerType::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, item->GetForcedFilePath(), download::DownloadInterruptReason::DOWNLOAD_INTERRUPT_REASON_NONE); + std::move(*callback).Run(item->GetForcedFilePath(), download::DownloadItem::TARGET_DISPOSITION_PROMPT, + download::DownloadDangerType::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, + download::DownloadItem::VALIDATED, + item->GetForcedFilePath(), + base::nullopt, + download::DownloadInterruptReason::DOWNLOAD_INTERRUPT_REASON_NONE); return true; } @@ -156,8 +162,11 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem* if (suggestedFilename.isEmpty()) suggestedFilename = toQt(item->GetTargetFilePath().AsUTF8Unsafe()); - if (suggestedFilename.isEmpty()) - suggestedFilename = QUrl::fromPercentEncoding(toQByteArray(item->GetURL().ExtractFileName())); + if (suggestedFilename.isEmpty()) { + GURL itemUrl = item->GetURL(); + if (!itemUrl.SchemeIs("about") && !itemUrl.SchemeIs("data")) + suggestedFilename = QUrl::fromPercentEncoding(toQByteArray(itemUrl.ExtractFileName())); + } if (suggestedFilename.isEmpty()) { suggestedFilename = QStringLiteral("qwe_download"); @@ -212,38 +221,38 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem* } if (!info.accepted) { - cancelDownload(callback); + cancelDownload(std::move(*callback)); return true; } base::FilePath filePathForCallback(toFilePathString(suggestedFile.absoluteFilePath())); - callback.Run(filePathForCallback, - download::DownloadItem::TARGET_DISPOSITION_OVERWRITE, - download::DownloadDangerType::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, - filePathForCallback.AddExtension(toFilePathString("download")), - download::DownloadInterruptReason::DOWNLOAD_INTERRUPT_REASON_NONE); + std::move(*callback).Run(filePathForCallback, + download::DownloadItem::TARGET_DISPOSITION_OVERWRITE, + download::DownloadDangerType::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, + download::DownloadItem::VALIDATED, + filePathForCallback.AddExtension(toFilePathString("download")), + base::nullopt, + download::DownloadInterruptReason::DOWNLOAD_INTERRUPT_REASON_NONE); } else - cancelDownload(callback); + cancelDownload(std::move(*callback)); return true; } void DownloadManagerDelegateQt::GetSaveDir(content::BrowserContext* browser_context, - base::FilePath* website_save_dir, - base::FilePath* download_save_dir, - bool* skip_dir_check) + base::FilePath* website_save_dir, + base::FilePath* download_save_dir) { static base::FilePath::StringType save_dir = toFilePathString(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)); *website_save_dir = base::FilePath(save_dir); *download_save_dir = base::FilePath(save_dir); - *skip_dir_check = true; } void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_contents, const base::FilePath &suggested_path, const base::FilePath::StringType &default_extension, bool can_save_as_complete, - const content::SavePackagePathPickedCallback &callback) + content::SavePackagePathPickedCallback callback) { Q_UNUSED(default_extension); Q_UNUSED(can_save_as_complete); @@ -286,7 +295,7 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content ++m_currentId, toQt(web_contents->GetURL()), download::DownloadItem::IN_PROGRESS, - 0, /* totalBytes */ + -1, /* totalBytes */ 0, /* receivedBytes */ QStringLiteral("application/x-mimearchive"), suggestedFilePath, @@ -310,29 +319,9 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content if (!info.accepted) return; - callback.Run(toFilePath(info.path), static_cast<content::SavePageType>(info.savePageFormat), - base::Bind(&DownloadManagerDelegateQt::savePackageDownloadCreated, - m_weakPtrFactory.GetWeakPtr())); -} - -bool DownloadManagerDelegateQt::IsMostRecentDownloadItemAtFilePath(download::DownloadItem *download) -{ - content::BrowserContext *context = content::DownloadItemUtils::GetBrowserContext(download); - std::vector<download::DownloadItem*> all_downloads; - - content::DownloadManager* manager = - content::BrowserContext::GetDownloadManager(context); - if (manager) - manager->GetAllDownloads(&all_downloads); - - for (const auto* item : all_downloads) { - if (item->GetGuid() == download->GetGuid() || - item->GetTargetFilePath() != download->GetTargetFilePath()) - continue; - if (item->GetState() == download::DownloadItem::IN_PROGRESS) - return false; - } - return true; + std::move(callback).Run(toFilePath(info.path), static_cast<content::SavePageType>(info.savePageFormat), + base::Bind(&DownloadManagerDelegateQt::savePackageDownloadCreated, + m_weakPtrFactory.GetWeakPtr())); } void DownloadManagerDelegateQt::savePackageDownloadCreated(download::DownloadItem *item) diff --git a/src/core/download_manager_delegate_qt.h b/src/core/download_manager_delegate_qt.h index 6acfa42ce..7f4f33702 100644 --- a/src/core/download_manager_delegate_qt.h +++ b/src/core/download_manager_delegate_qt.h @@ -70,22 +70,19 @@ class DownloadManagerDelegateQt public: DownloadManagerDelegateQt(ProfileAdapter *profileAdapter); ~DownloadManagerDelegateQt(); - void GetNextId(const content::DownloadIdCallback& callback) override; + void GetNextId(content::DownloadIdCallback callback) override; - bool DetermineDownloadTarget(download::DownloadItem* item, - const content::DownloadTargetCallback& callback) override; + bool DetermineDownloadTarget(download::DownloadItem *item, + content::DownloadTargetCallback *callback) override; void GetSaveDir(content::BrowserContext* browser_context, base::FilePath* website_save_dir, - base::FilePath* download_save_dir, - bool* skip_dir_check) override; + base::FilePath* download_save_dir) override; void ChooseSavePath(content::WebContents *web_contents, const base::FilePath &suggested_path, const base::FilePath::StringType &default_extension, bool can_save_as_complete, - const content::SavePackagePathPickedCallback &callback) override; - bool IsMostRecentDownloadItemAtFilePath(download::DownloadItem* download) override; - + content::SavePackagePathPickedCallback callback) override; void cancelDownload(quint32 downloadId); void pauseDownload(quint32 downloadId); @@ -99,7 +96,7 @@ public: void OnDownloadDestroyed(download::DownloadItem *download) override; private: - void cancelDownload(const content::DownloadTargetCallback& callback); + void cancelDownload(content::DownloadTargetCallback callback); download::DownloadItem *findDownloadById(quint32 downloadId); void savePackageDownloadCreated(download::DownloadItem *download); ProfileAdapter *m_profileAdapter; diff --git a/src/core/extensions/component_extension_resource_manager_qt.cpp b/src/core/extensions/component_extension_resource_manager_qt.cpp index bb1dd045c..fb6bb5950 100644 --- a/src/core/extensions/component_extension_resource_manager_qt.cpp +++ b/src/core/extensions/component_extension_resource_manager_qt.cpp @@ -44,12 +44,19 @@ #include "component_extension_resource_manager_qt.h" +#include "base/check.h" #include "base/logging.h" #include "base/path_service.h" #include "base/stl_util.h" #include "base/values.h" - #include "chrome/grit/component_extension_resources_map.h" +#include "content/public/browser/browser_thread.h" +#include "extensions/common/constants.h" +#include "pdf/buildflags.h" + +#if BUILDFLAG(ENABLE_PDF) +#include "qtwebengine/browser/pdf/pdf_extension_util.h" +#endif // BUILDFLAG(ENABLE_PDF) namespace extensions { @@ -57,6 +64,16 @@ ComponentExtensionResourceManagerQt::ComponentExtensionResourceManagerQt() { AddComponentResourceEntries(kComponentExtensionResources, kComponentExtensionResourcesSize); + +#if BUILDFLAG(ENABLE_PDF) + base::Value dict(base::Value::Type::DICTIONARY); + pdf_extension_util::AddStrings(pdf_extension_util::PdfViewerContext::kPdfViewer, &dict); + pdf_extension_util::AddAdditionalData(&dict); + + ui::TemplateReplacements pdf_viewer_replacements; + ui::TemplateReplacementsFromDictionaryValue(base::Value::AsDictionaryValue(dict), &pdf_viewer_replacements); + template_replacements_[extension_misc::kPdfExtensionId] = std::move(pdf_viewer_replacements); +#endif } ComponentExtensionResourceManagerQt::~ComponentExtensionResourceManagerQt() {} @@ -85,19 +102,36 @@ bool ComponentExtensionResourceManagerQt::IsComponentExtensionResource(const bas return false; } -const ui::TemplateReplacements *ComponentExtensionResourceManagerQt::GetTemplateReplacementsForExtension(const std::string &) const +const ui::TemplateReplacements *ComponentExtensionResourceManagerQt::GetTemplateReplacementsForExtension(const std::string &extension_id) const { - return nullptr; + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + auto it = template_replacements_.find(extension_id); + return it != template_replacements_.end() ? &it->second : nullptr; } void ComponentExtensionResourceManagerQt::AddComponentResourceEntries(const GritResourceMap *entries, size_t size) { + base::FilePath gen_folder_path = base::FilePath().AppendASCII("@out_folder@/gen/chrome/browser/resources/"); + gen_folder_path = gen_folder_path.NormalizePathSeparators(); + for (size_t i = 0; i < size; ++i) { base::FilePath resource_path = base::FilePath().AppendASCII(entries[i].name); resource_path = resource_path.NormalizePathSeparators(); - DCHECK(!base::Contains(path_to_resource_id_, resource_path)); - path_to_resource_id_[resource_path] = entries[i].value; + + if (!gen_folder_path.IsParent(resource_path)) { + DCHECK(!base::Contains(path_to_resource_id_, resource_path)); + path_to_resource_id_[resource_path] = entries[i].value; + } else { + // If the resource is a generated file, strip the generated folder's path, + // so that it can be served from a normal URL (as if it were not + // generated). + base::FilePath effective_path = + base::FilePath().AppendASCII(resource_path.AsUTF8Unsafe().substr( + gen_folder_path.value().length())); + DCHECK(!base::Contains(path_to_resource_id_, effective_path)); + path_to_resource_id_[effective_path] = entries[i].value; + } } } diff --git a/src/core/extensions/component_extension_resource_manager_qt.h b/src/core/extensions/component_extension_resource_manager_qt.h index b719c8960..6131e91aa 100644 --- a/src/core/extensions/component_extension_resource_manager_qt.h +++ b/src/core/extensions/component_extension_resource_manager_qt.h @@ -47,6 +47,7 @@ #include <map> #include "base/files/file_path.h" +#include "base/macros.h" #include "extensions/browser/component_extension_resource_manager.h" struct GritResourceMap; @@ -72,6 +73,9 @@ private: // IsComponentExtensionResource. std::map<base::FilePath, int> path_to_resource_id_; + // A map from an extension ID to its i18n template replacements. + std::map<std::string, ui::TemplateReplacements> template_replacements_; + DISALLOW_COPY_AND_ASSIGN(ComponentExtensionResourceManagerQt); }; diff --git a/src/core/extensions/extension_host_delegate_qt.cpp b/src/core/extensions/extension_host_delegate_qt.cpp new file mode 100644 index 000000000..1a44dee7a --- /dev/null +++ b/src/core/extensions/extension_host_delegate_qt.cpp @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "extension_host_delegate_qt.h" +#include "extension_web_contents_observer_qt.h" +#include "media_capture_devices_dispatcher.h" +#include "extension_system_qt.h" + +#include "extensions/browser/extension_host.h" + +namespace extensions { + +ExtensionHostDelegateQt::ExtensionHostDelegateQt() +{ +} + +void ExtensionHostDelegateQt::OnExtensionHostCreated(content::WebContents *web_contents) +{ + extensions::ExtensionWebContentsObserverQt::CreateForWebContents(web_contents); +} + +void ExtensionHostDelegateQt::OnRenderViewCreatedForBackgroundPage(ExtensionHost *host) +{ + Q_UNUSED(host); +} + +content::JavaScriptDialogManager *ExtensionHostDelegateQt::GetJavaScriptDialogManager() +{ + Q_UNREACHABLE(); + return nullptr; +} + +void ExtensionHostDelegateQt::CreateTab(std::unique_ptr<content::WebContents> web_contents, + const std::string &extension_id, + WindowOpenDisposition disposition, + const gfx::Rect &initial_rect, + bool user_gesture) +{ + Q_UNUSED(web_contents); + Q_UNUSED(extension_id); + Q_UNUSED(disposition); + Q_UNUSED(initial_rect); + Q_UNUSED(user_gesture); + + Q_UNREACHABLE(); +} + +void ExtensionHostDelegateQt::ProcessMediaAccessRequest(content::WebContents *web_contents, + const content::MediaStreamRequest &request, + content::MediaResponseCallback callback, + const Extension *extension) +{ + Q_UNUSED(extension); + + QtWebEngineCore::MediaCaptureDevicesDispatcher::GetInstance()->processMediaAccessRequest(web_contents, request, std::move(callback)); +} + +bool ExtensionHostDelegateQt::CheckMediaAccessPermission(content::RenderFrameHost *render_frame_host, + const GURL &security_origin, + blink::mojom::MediaStreamType type, + const Extension *extension) +{ + Q_UNUSED(render_frame_host); + Q_UNUSED(security_origin); + Q_UNUSED(type); + Q_UNUSED(extension); + + Q_UNREACHABLE(); + return false; +} + +content::PictureInPictureResult ExtensionHostDelegateQt::EnterPictureInPicture(content::WebContents *web_contents, + const viz::SurfaceId &surface_id, + const gfx::Size &natural_size) +{ + Q_UNUSED(web_contents); + Q_UNUSED(surface_id); + Q_UNUSED(natural_size); + + Q_UNREACHABLE(); + return content::PictureInPictureResult::kNotSupported; +} + +void ExtensionHostDelegateQt::ExitPictureInPicture() +{ + Q_UNREACHABLE(); +} + +} // namespace extensions diff --git a/src/core/renderer_host/resource_dispatcher_host_delegate_qt.h b/src/core/extensions/extension_host_delegate_qt.h index 3039fd03e..42ff56a53 100644 --- a/src/core/renderer_host/resource_dispatcher_host_delegate_qt.h +++ b/src/core/extensions/extension_host_delegate_qt.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWebEngine module of the Qt Toolkit. @@ -37,41 +37,41 @@ ** ****************************************************************************/ -#ifndef RESOURCE_DISPATCHER_HOST_DELEGATE_QT_H -#define RESOURCE_DISPATCHER_HOST_DELEGATE_QT_H +#ifndef EXTENSION_HOST_DELEGATE_QT_H +#define EXTENSION_HOST_DELEGATE_QT_H -#include "content/public/browser/resource_dispatcher_host_delegate.h" -#include "extensions/buildflags/buildflags.h" +#include "extensions/browser/extension_host_delegate.h" -#include "web_contents_adapter_client.h" +namespace extensions { -namespace QtWebEngineCore { - -class ResourceDispatcherHostDelegateQt : public content::ResourceDispatcherHostDelegate { +class ExtensionHostDelegateQt : public ExtensionHostDelegate +{ public: - // If the stream will be rendered in a BrowserPlugin, |payload| will contain - // the data that should be given to the old ResourceHandler to forward to the - // renderer process. - bool ShouldInterceptResourceAsStream(net::URLRequest *request, - const std::string &mime_type, - GURL *origin, - std::string *payload) override; - - // Informs the delegate that a Stream was created. The Stream can be read from - // the blob URL of the Stream, but can only be read once. - void OnStreamCreated(net::URLRequest *request, - std::unique_ptr<content::StreamInfo> stream) override; -private: -#if BUILDFLAG(ENABLE_EXTENSIONS) - struct StreamTargetInfo { - std::string extension_id; - std::string view_id; - }; - std::map<net::URLRequest *, StreamTargetInfo> stream_target_info_; -#endif + ExtensionHostDelegateQt(); + // EtensionHostDelegate implementation. + void OnExtensionHostCreated(content::WebContents *web_contents) override; + void OnRenderViewCreatedForBackgroundPage(ExtensionHost *host) override; + content::JavaScriptDialogManager *GetJavaScriptDialogManager() override; + void CreateTab(std::unique_ptr<content::WebContents> web_contents, + const std::string &extension_id, + WindowOpenDisposition disposition, + const gfx::Rect &initial_rect, + bool user_gesture) override; + void ProcessMediaAccessRequest(content::WebContents *web_contents, + const content::MediaStreamRequest &request, + content::MediaResponseCallback callback, + const Extension *extension) override; + bool CheckMediaAccessPermission(content::RenderFrameHost *render_frame_host, + const GURL &security_origin, + blink::mojom::MediaStreamType type, + const Extension *extension) override; + content::PictureInPictureResult EnterPictureInPicture(content::WebContents *web_contents, + const viz::SurfaceId &surface_id, + const gfx::Size &natural_size) override; + void ExitPictureInPicture() override; }; -} // namespace QtWebEngineCore +} // namespace extensions -#endif // RESOURCE_DISPATCHER_HOST_DELEGATE_QT_H +#endif // EXTENSION_HOST_DELEGATE_QT_H diff --git a/src/core/extensions/extension_system_qt.cpp b/src/core/extensions/extension_system_qt.cpp index fbe98099c..285b27729 100644 --- a/src/core/extensions/extension_system_qt.cpp +++ b/src/core/extensions/extension_system_qt.cpp @@ -61,6 +61,7 @@ #include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" +#include "chrome/common/buildflags.h" #include "components/crx_file/id_util.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_task_traits.h" @@ -83,18 +84,16 @@ #include "extensions/browser/quota_service.h" #include "extensions/browser/renderer_startup_helper.h" #include "extensions/browser/runtime_data.h" -#include "extensions/browser/shared_user_script_master.h" +#include "extensions/browser/shared_user_script_manager.h" #include "extensions/browser/service_worker_manager.h" #include "extensions/browser/value_store/value_store_factory_impl.h" #include "extensions/common/constants.h" -#include "extensions/common/extension_messages.h" #include "extensions/common/manifest_constants.h" #include "extensions/common/manifest_handlers/mime_types_handler.h" #include "extensions/common/manifest_url_handlers.h" -#include "ui/base/resource/resource_bundle.h" -#include "chrome/grit/component_extension_resources.h" -#include "chrome/grit/browser_resources.h" #include "net/base/mime_util.h" +#include "qtwebengine/grit/qt_webengine_resources.h" +#include "ui/base/resource/resource_bundle.h" using content::BrowserThread; @@ -136,7 +135,8 @@ public: // This should return what verification mode is appropriate for the given // extension, if any. - bool ShouldBeVerified(const Extension &extension) override { return false; } + VerifierSourceType GetVerifierSourceType(const Extension &extension) override + { return VerifierSourceType::NONE; } // Should return the public key to use for validating signatures via the two // out parameters. @@ -174,7 +174,7 @@ void ExtensionSystemQt::LoadExtension(std::string extension_id, std::unique_ptr< if (!extension.get()) LOG(ERROR) << error; - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, + base::PostTask(FROM_HERE, {content::BrowserThread::IO}, base::Bind(&InfoMap::AddExtension, base::Unretained(info_map()), base::RetainedRef(extension), @@ -223,11 +223,12 @@ void ExtensionSystemQt::NotifyExtensionLoaded(const Extension *extension) // Register plugins included with the extension. // Implementation based on PluginManager::OnExtensionLoaded. const MimeTypesHandler *handler = MimeTypesHandler::GetHandler(extension); - if (handler && !handler->handler_url().empty()) { + if (handler && handler->HasPlugin()) { content::WebPluginInfo info; info.type = content::WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN; info.name = base::UTF8ToUTF16(extension->name()); - info.path = base::FilePath::FromUTF8Unsafe(extension->url().spec()); + info.path = handler->GetPluginPath(); + info.background_color = handler->GetBackgroundColor(); for (std::set<std::string>::const_iterator mime_type = handler->mime_type_set().begin(); mime_type != handler->mime_type_set().end(); ++mime_type) { content::WebPluginMimeType mime_type_info; @@ -278,9 +279,9 @@ ManagementPolicy *ExtensionSystemQt::management_policy() return nullptr; } -SharedUserScriptMaster *ExtensionSystemQt::shared_user_script_master() +SharedUserScriptManager *ExtensionSystemQt::shared_user_script_manager() { - return shared_user_script_master_.get(); + return shared_user_script_manager_.get(); } StateStore *ExtensionSystemQt::state_store() @@ -349,8 +350,8 @@ void ExtensionSystemQt::Init(bool extensions_enabled) quota_service_.reset(new QuotaService); app_sorting_.reset(new NullAppSorting); - shared_user_script_master_ = - std::make_unique<SharedUserScriptMaster>(browser_context_); + shared_user_script_manager_ = + std::make_unique<SharedUserScriptManager>(browser_context_); // Make the chrome://extension-icon/ resource available. // content::URLDataSource::Add(browser_context_, new ExtensionIconSource(browser_context_)); @@ -358,20 +359,30 @@ void ExtensionSystemQt::Init(bool extensions_enabled) if (extensions_enabled) { // Inform the rest of the extensions system to start. ready_.Signal(); - content::NotificationService::current()->Notify( - NOTIFICATION_EXTENSIONS_READY_DEPRECATED, - content::Source<content::BrowserContext>(browser_context_), - content::NotificationService::NoDetails()); - - std::string pdf_manifest = ui::ResourceBundle::GetSharedInstance().GetRawDataResource(IDR_PDF_MANIFEST).as_string(); - base::ReplaceFirstSubstringAfterOffset(&pdf_manifest, 0, "<NAME>", "chromium-pdf"); - - std::unique_ptr<base::DictionaryValue> pdfManifestDict = ParseManifest(pdf_manifest); - base::FilePath path; - base::PathService::Get(base::DIR_QT_LIBRARY_DATA, &path); - path = path.Append(base::FilePath(FILE_PATH_LITERAL("pdf"))); - std::string id = GenerateId(pdfManifestDict.get(), path); - LoadExtension(id, std::move(pdfManifestDict), path); + + { + std::string pdf_manifest = ui::ResourceBundle::GetSharedInstance().GetRawDataResource(IDR_PDF_MANIFEST).as_string(); + base::ReplaceFirstSubstringAfterOffset(&pdf_manifest, 0, "<NAME>", "chromium-pdf"); + + std::unique_ptr<base::DictionaryValue> pdfManifestDict = ParseManifest(pdf_manifest); + base::FilePath path; + base::PathService::Get(base::DIR_QT_LIBRARY_DATA, &path); + path = path.Append(base::FilePath(FILE_PATH_LITERAL("pdf"))); + std::string id = GenerateId(pdfManifestDict.get(), path); + LoadExtension(id, std::move(pdfManifestDict), path); + } + +#if BUILDFLAG(ENABLE_HANGOUT_SERVICES_EXTENSION) + { + std::string hangout_manifest = ui::ResourceBundle::GetSharedInstance().GetRawDataResource(IDR_HANGOUT_SERVICES_MANIFEST).as_string(); + std::unique_ptr<base::DictionaryValue> hangoutManifestDict = ParseManifest(hangout_manifest); + base::FilePath path; + base::PathService::Get(base::DIR_QT_LIBRARY_DATA, &path); + path = path.Append(base::FilePath(FILE_PATH_LITERAL("hangout_services"))); + std::string id = GenerateId(hangoutManifestDict.get(), path); + LoadExtension(id, std::move(hangoutManifestDict), path); + } +#endif // BUILDFLAG(ENABLE_HANGOUT_SERVICES_EXTENSION) } } @@ -390,40 +401,33 @@ std::unique_ptr<ExtensionSet> ExtensionSystemQt::GetDependentExtensions(const Ex return base::WrapUnique(new ExtensionSet()); } -#if !defined(TOOLKIT_QT) -void ExtensionSystemQt::InstallUpdate(const std::string &extension_id, - const std::string &public_key, - const base::FilePath &unpacked_dir, - bool install_immediately, - InstallUpdateCallback install_update_callback) -{ - NOTREACHED() << "Not yet implemented"; - base::DeleteFile(unpacked_dir, true /* recursive */); - std::move(install_update_callback).Run(CrxInstallError(CrxInstallErrorType::DECLINED, CrxInstallErrorDetail::DISALLOWED_BY_POLICY)); -} -#endif - void ExtensionSystemQt::RegisterExtensionWithRequestContexts(const Extension *extension, - const base::Closure &callback) + base::OnceClosure callback) { base::Time install_time = base::Time::Now(); bool incognito_enabled = false; bool notifications_disabled = false; - base::PostTaskWithTraitsAndReply( + base::PostTaskAndReply( FROM_HERE, {BrowserThread::IO}, base::Bind(&InfoMap::AddExtension, info_map(), base::RetainedRef(extension), install_time, incognito_enabled, notifications_disabled), - callback); + std::move(callback)); } void ExtensionSystemQt::UnregisterExtensionWithRequestContexts(const std::string &extension_id, const UnloadedExtensionReason reason) { - base::PostTaskWithTraits( + base::PostTask( FROM_HERE, {BrowserThread::IO}, base::Bind(&InfoMap::RemoveExtension, info_map(), extension_id, reason)); } + +bool ExtensionSystemQt::is_ready() const +{ + return ready_.is_signaled(); +} + } // namespace extensions diff --git a/src/core/extensions/extension_system_qt.h b/src/core/extensions/extension_system_qt.h index 04bffb74d..59835657a 100644 --- a/src/core/extensions/extension_system_qt.h +++ b/src/core/extensions/extension_system_qt.h @@ -89,7 +89,7 @@ public: RuntimeData *runtime_data() override; ManagementPolicy *management_policy() override; ServiceWorkerManager *service_worker_manager() override; - SharedUserScriptMaster *shared_user_script_master() override; + SharedUserScriptManager *shared_user_script_manager() override; StateStore *state_store() override; StateStore *rules_store() override; scoped_refptr<ValueStoreFactory> store_factory() override; @@ -98,7 +98,7 @@ public: AppSorting *app_sorting() override; void RegisterExtensionWithRequestContexts(const Extension *extension, - const base::Closure &callback) override; + base::OnceClosure callback) override; void UnregisterExtensionWithRequestContexts(const std::string &extension_id, const UnloadedExtensionReason reason) override; @@ -106,20 +106,14 @@ public: ContentVerifier *content_verifier() override; std::unique_ptr<ExtensionSet> GetDependentExtensions(const Extension *extension) override; -#if !defined(TOOLKIT_QT) - void InstallUpdate(const std::string &extension_id, - const std::string &public_key, - const base::FilePath &unpacked_dir, - bool install_immediately, - InstallUpdateCallback install_update_callback) override; -#endif // TOOLKIT_QT - //friend class ExtensionSystemSharedFactory; - bool FinishDelayedInstallationIfReady(const std::string &extension_id, bool install_immediately) override; void Init(bool extensions_enabled); const base::OneShotEvent &ready() const override { return ready_; } + bool is_ready() const override; + + void PerformActionBasedOnOmahaAttributes(const std::string &, const base::Value &) override { /* fixme? */} private: void OnExtensionRegisteredWithRequestContexts(scoped_refptr<const extensions::Extension> extension); @@ -135,7 +129,7 @@ private: std::unique_ptr<RuntimeData> runtime_data_; std::unique_ptr<QuotaService> quota_service_; std::unique_ptr<AppSorting> app_sorting_; - std::unique_ptr<SharedUserScriptMaster> shared_user_script_master_; + std::unique_ptr<SharedUserScriptManager> shared_user_script_manager_; // For verifying the contents of extensions read from disk. diff --git a/src/core/extensions/extension_web_contents_observer_qt.cpp b/src/core/extensions/extension_web_contents_observer_qt.cpp index 5b1514bb4..e336f70b4 100644 --- a/src/core/extensions/extension_web_contents_observer_qt.cpp +++ b/src/core/extensions/extension_web_contents_observer_qt.cpp @@ -43,13 +43,17 @@ #include "extension_web_contents_observer_qt.h" +#include "components/guest_view/browser/guest_view_base.h" #include "content/public/browser/child_process_security_policy.h" -#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/render_view_host.h" #include "content/public/common/url_constants.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/manifest.h" +#include "render_widget_host_view_qt.h" + namespace extensions { ExtensionWebContentsObserverQt::ExtensionWebContentsObserverQt(content::WebContents *web_contents) @@ -85,6 +89,16 @@ void ExtensionWebContentsObserverQt::RenderFrameCreated(content::RenderFrameHost policy->GrantRequestOrigin(process_id, url::Origin::Create(GURL(content::kChromeUIResourcesURL))); } +void ExtensionWebContentsObserverQt::RenderViewCreated(content::RenderViewHost *render_view_host) +{ + if (web_contents()->IsInnerWebContentsForGuest()) { + content::RenderWidgetHost *render_widget_host = render_view_host->GetWidget(); + content::WebContents *parent_web_contents = guest_view::GuestViewBase::GetTopLevelWebContents(web_contents()); + QtWebEngineCore::RenderWidgetHostViewQt *parent_rwhv = static_cast<QtWebEngineCore::RenderWidgetHostViewQt *>(parent_web_contents->GetRenderWidgetHostView()); + parent_rwhv->setGuest(static_cast<content::RenderWidgetHostImpl *>(render_widget_host)); + } +} + WEB_CONTENTS_USER_DATA_KEY_IMPL(ExtensionWebContentsObserverQt) } // namespace extensions diff --git a/src/core/extensions/extension_web_contents_observer_qt.h b/src/core/extensions/extension_web_contents_observer_qt.h index 658966b31..c0269e4f5 100644 --- a/src/core/extensions/extension_web_contents_observer_qt.h +++ b/src/core/extensions/extension_web_contents_observer_qt.h @@ -61,6 +61,7 @@ public: // content::WebContentsObserver overrides. void RenderFrameCreated(content::RenderFrameHost *render_frame_host) override; + void RenderViewCreated(content::RenderViewHost *render_view_host) override; private: friend class content::WebContentsUserData<ExtensionWebContentsObserverQt>; diff --git a/src/core/extensions/extensions_api_client_qt.cpp b/src/core/extensions/extensions_api_client_qt.cpp index 731b79a63..925fd10da 100644 --- a/src/core/extensions/extensions_api_client_qt.cpp +++ b/src/core/extensions/extensions_api_client_qt.cpp @@ -43,13 +43,14 @@ // found in the LICENSE file. #include "extensions_api_client_qt.h" +#include "messaging_delegate_qt.h" #include <memory> -//#include "base/memory/ptr_util.h" -#include "extension_web_contents_observer_qt.h" #include "components/pdf/browser/pdf_web_contents_helper.h" +#include "extension_web_contents_observer_qt.h" #include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h" #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest_delegate.h" +#include "mime_handler_view_guest_delegate_qt.h" #include "printing/print_view_manager_qt.h" namespace extensions { @@ -67,12 +68,12 @@ AppViewGuestDelegate *ExtensionsAPIClientQt::CreateAppViewGuestDelegate() const std::unique_ptr<guest_view::GuestViewManagerDelegate> ExtensionsAPIClientQt::CreateGuestViewManagerDelegate(content::BrowserContext *context) const { - return std::make_unique<guest_view::GuestViewManagerDelegate>(); + return std::make_unique<extensions::ExtensionsGuestViewManagerDelegate>(context); } std::unique_ptr<MimeHandlerViewGuestDelegate> ExtensionsAPIClientQt::CreateMimeHandlerViewGuestDelegate(MimeHandlerViewGuest *guest) const { - return std::make_unique<MimeHandlerViewGuestDelegate>(); + return std::make_unique<MimeHandlerViewGuestDelegateQt>(guest); } void ExtensionsAPIClientQt::AttachWebContentsHelpers(content::WebContents *web_contents) const @@ -82,4 +83,11 @@ void ExtensionsAPIClientQt::AttachWebContentsHelpers(content::WebContents *web_c ExtensionWebContentsObserverQt::CreateForWebContents(web_contents); } +MessagingDelegate *ExtensionsAPIClientQt::GetMessagingDelegate() +{ + if (!m_messagingDelegate) + m_messagingDelegate = std::make_unique<MessagingDelegateQt>(); + return m_messagingDelegate.get(); +} + } // namespace extensions diff --git a/src/core/extensions/extensions_api_client_qt.h b/src/core/extensions/extensions_api_client_qt.h index 2fa69f539..b1b6356e8 100644 --- a/src/core/extensions/extensions_api_client_qt.h +++ b/src/core/extensions/extensions_api_client_qt.h @@ -49,6 +49,8 @@ namespace extensions { +class MessagingDelegate; + class ExtensionsAPIClientQt : public ExtensionsAPIClient { public: @@ -61,6 +63,10 @@ public: std::unique_ptr<MimeHandlerViewGuestDelegate> CreateMimeHandlerViewGuestDelegate(MimeHandlerViewGuest *guest) const override; void AttachWebContentsHelpers(content::WebContents *web_contents) const override; + MessagingDelegate *GetMessagingDelegate() override; + +private: + std::unique_ptr<MessagingDelegate> m_messagingDelegate; }; } // namespace extensions diff --git a/src/core/extensions/extensions_browser_client_qt.cpp b/src/core/extensions/extensions_browser_client_qt.cpp index 59c15d2f5..501252823 100644 --- a/src/core/extensions/extensions_browser_client_qt.cpp +++ b/src/core/extensions/extensions_browser_client_qt.cpp @@ -49,39 +49,38 @@ #include "base/files/file_path.h" #include "base/memory/weak_ptr.h" #include "base/path_service.h" -#include "base/strings/stringprintf.h" #include "base/task/post_task.h" #include "base/memory/ref_counted_memory.h" +#include "chrome/browser/extensions/api/generated_api_registration.h" #include "chrome/browser/profiles/profile.h" #include "content/public/browser/browser_context.h" -#include "content/public/browser/browser_thread.h" #include "content/public/browser/render_frame_host.h" #include "extensions/browser/api/extensions_api_client.h" #include "extensions/browser/api/runtime/runtime_api_delegate.h" -#include "extensions/browser/app_sorting.h" #include "extensions/browser/core_extensions_browser_api_provider.h" #include "extensions/browser/event_router.h" #include "extensions/browser/extension_host_delegate.h" #include "extensions/browser/extension_protocols.h" -#include "extensions/browser/mojo/interface_registration.h" +#include "extensions/browser/extensions_browser_api_provider.h" +#include "extensions/browser/extensions_browser_interface_binders.h" #include "extensions/browser/url_request_util.h" #include "extensions/common/file_util.h" -#include "net/base/completion_once_callback.h" #include "net/base/mime_util.h" -#include "net/url_request/url_request_simple_job.h" +#include "qtwebengine/browser/extensions/api/generated_api_registration.h" #include "services/network/public/mojom/url_loader.mojom.h" +#include "services/network/public/mojom/url_response_head.mojom.h" +#include "third_party/zlib/google/compression_utils.h" #include "ui/base/resource/resource_bundle.h" #include "component_extension_resource_manager_qt.h" #include "extension_system_factory_qt.h" #include "extension_web_contents_observer_qt.h" #include "extensions_api_client_qt.h" -#include "extensions_browser_api_provider_qt.h" #include "extensions_browser_client_qt.h" +#include "extension_host_delegate_qt.h" #include "web_engine_library_info.h" using content::BrowserContext; -using content::BrowserThread; namespace { @@ -102,79 +101,195 @@ void DetermineCharset(const std::string &mime_type, } } -// A request for an extension resource in a Chrome .pak file. These are used -// by component extensions. -class URLRequestResourceBundleJob : public net::URLRequestSimpleJob +scoped_refptr<base::RefCountedMemory> GetResource(int resource_id, const std::string &extension_id) +{ + const ui::ResourceBundle &rb = ui::ResourceBundle::GetSharedInstance(); + scoped_refptr<base::RefCountedMemory> bytes = rb.LoadDataResourceBytes(resource_id); + auto *replacements = extensions::ExtensionsBrowserClient::Get()->GetComponentExtensionResourceManager() + ? extensions::ExtensionsBrowserClient::Get()->GetComponentExtensionResourceManager()->GetTemplateReplacementsForExtension( + extension_id) + : nullptr; + + if (replacements) { + base::StringPiece input(reinterpret_cast<const char *>(bytes->front()), bytes->size()); + std::string temp_str = ui::ReplaceTemplateExpressions(input, *replacements); + DCHECK(!temp_str.empty()); + return base::RefCountedString::TakeString(&temp_str); + } + return bytes; +} + +// Loads an extension resource in a Chrome .pak file. These are used by +// component extensions. +class ResourceBundleFileLoader : public network::mojom::URLLoader { public: - URLRequestResourceBundleJob(net::URLRequest *request, net::NetworkDelegate *network_delegate, - const base::FilePath &filename, int resource_id, - const std::string &content_security_policy, bool send_cors_header) - : net::URLRequestSimpleJob(request, network_delegate) - , filename_(filename) - , resource_id_(resource_id) - , weak_factory_(this) + static void CreateAndStart(const network::ResourceRequest &request, + mojo::PendingReceiver<network::mojom::URLLoader> loader, + mojo::PendingRemote<network::mojom::URLLoaderClient> client_info, + const base::FilePath &filename, int resource_id, + const std::string &content_security_policy, bool send_cors_header) { - // Leave cache headers out of resource bundle requests. - response_info_.headers = extensions::BuildHttpHeaders(content_security_policy, send_cors_header, base::Time()); + // Owns itself. Will live as long as its URLLoader and URLLoaderClientPtr + // bindings are alive - essentially until either the client gives up or all + // file data has been sent to it. + auto *bundle_loader = new ResourceBundleFileLoader(content_security_policy, send_cors_header); + bundle_loader->Start(request, std::move(loader), std::move(client_info), filename, resource_id); } - int GetRefCountedData(std::string *mime_type, std::string *charset, scoped_refptr<base::RefCountedMemory> *data, - net::CompletionOnceCallback callback) const override + + // mojom::URLLoader implementation: + void FollowRedirect(const std::vector<std::string> &removed_headers, + const net::HttpRequestHeaders &modified_headers, + const net::HttpRequestHeaders &modified_cors_exempt_headers, + const base::Optional<GURL> &new_url) override { - const ui::ResourceBundle &rb = ui::ResourceBundle::GetSharedInstance(); - *data = rb.LoadDataResourceBytes(resource_id_); + NOTREACHED() << "No redirects for local file loads."; + } + // Current implementation reads all resource data at start of resource + // load, so priority, and pausing is not currently implemented. + void SetPriority(net::RequestPriority priority, int32_t intra_priority_value) override {} + void PauseReadingBodyFromNet() override {} + void ResumeReadingBodyFromNet() override {} - // Add the Content-Length header now that we know the resource length. - response_info_.headers->AddHeader(base::StringPrintf("%s: %s", net::HttpRequestHeaders::kContentLength, - base::NumberToString((*data)->size()).c_str())); +private: + ResourceBundleFileLoader(const std::string &content_security_policy, bool send_cors_header) + { + response_headers_ = extensions::BuildHttpHeaders(content_security_policy, send_cors_header, base::Time()); + } + ~ResourceBundleFileLoader() override = default; - std::string *read_mime_type = new std::string; - base::PostTaskWithTraitsAndReplyWithResult( - FROM_HERE, { base::MayBlock() }, - base::BindOnce(&net::GetMimeTypeFromFile, filename_, base::Unretained(read_mime_type)), - base::BindOnce(&URLRequestResourceBundleJob::OnMimeTypeRead, weak_factory_.GetWeakPtr(), mime_type, - charset, *data, base::Owned(read_mime_type), std::move(callback))); + void Start(const network::ResourceRequest &request, + mojo::PendingReceiver<network::mojom::URLLoader> loader, + mojo::PendingRemote<network::mojom::URLLoaderClient> client_info_remote, + const base::FilePath &filename, int resource_id) + { + client_.Bind(std::move(client_info_remote)); + receiver_.Bind(std::move(loader)); + receiver_.set_disconnect_handler(base::BindOnce( + &ResourceBundleFileLoader::OnReceiverError, base::Unretained(this))); + client_.set_disconnect_handler(base::BindOnce( + &ResourceBundleFileLoader::OnMojoDisconnect, base::Unretained(this))); + auto data = GetResource(resource_id, request.url.host()); - return net::ERR_IO_PENDING; + std::string *read_mime_type = new std::string; + base::PostTaskAndReplyWithResult( + FROM_HERE, { base::ThreadPool(), base::MayBlock() }, + base::BindOnce(&net::GetMimeTypeFromFile, filename, base::Unretained(read_mime_type)), + base::BindOnce(&ResourceBundleFileLoader::OnMimeTypeRead, weak_factory_.GetWeakPtr(), std::move(data), + base::Owned(read_mime_type))); } - void GetResponseInfo(net::HttpResponseInfo *info) override { *info = response_info_; } + void OnMimeTypeRead(scoped_refptr<base::RefCountedMemory> data, std::string *read_mime_type, bool read_result) + { + auto head = network::mojom::URLResponseHead::New(); + head->request_start = base::TimeTicks::Now(); + head->response_start = base::TimeTicks::Now(); + head->content_length = data->size(); + head->mime_type = *read_mime_type; + DetermineCharset(head->mime_type, data.get(), &head->charset); + mojo::DataPipe pipe(data->size()); + if (!pipe.consumer_handle.is_valid()) { + client_->OnComplete(network::URLLoaderCompletionStatus(net::ERR_FAILED)); + client_.reset(); + MaybeDeleteSelf(); + return; + } + head->headers = response_headers_; + head->headers->AddHeader(net::HttpRequestHeaders::kContentLength, + base::NumberToString(head->content_length).c_str()); + if (!head->mime_type.empty()) { + head->headers->AddHeader(net::HttpRequestHeaders::kContentType, head->mime_type.c_str()); + } + client_->OnReceiveResponse(std::move(head)); + client_->OnStartLoadingResponseBody(std::move(pipe.consumer_handle)); -private: - ~URLRequestResourceBundleJob() override {} + uint32_t write_size = data->size(); + MojoResult result = pipe.producer_handle->WriteData(data->front(), &write_size, MOJO_WRITE_DATA_FLAG_NONE); + OnFileWritten(result); + } - void OnMimeTypeRead(std::string *out_mime_type, std::string *charset, scoped_refptr<base::RefCountedMemory> data, - std::string *read_mime_type, net::CompletionOnceCallback callback, bool read_result) + void OnMojoDisconnect() { - response_info_.headers->AddHeader( - base::StringPrintf("%s: %s", net::HttpRequestHeaders::kContentType, read_mime_type->c_str())); - *out_mime_type = *read_mime_type; - DetermineCharset(*read_mime_type, data.get(), charset); - int result = read_result ? net::OK : net::ERR_INVALID_URL; - std::move(callback).Run(result); + client_.reset(); + MaybeDeleteSelf(); } - // We need the filename of the resource to determine the mime type. - base::FilePath filename_; + void OnReceiverError() + { + receiver_.reset(); + MaybeDeleteSelf(); + } + + void MaybeDeleteSelf() + { + if (!receiver_.is_bound() && !client_.is_bound()) + delete this; + } - // The resource to load. - int resource_id_; + void OnFileWritten(MojoResult result) + { + // All the data has been written now. The consumer will be notified that + // there will be no more data to read from now. + if (result == MOJO_RESULT_OK) + client_->OnComplete(network::URLLoaderCompletionStatus(net::OK)); + else + client_->OnComplete(network::URLLoaderCompletionStatus(net::ERR_FAILED)); + client_.reset(); + MaybeDeleteSelf(); + } - net::HttpResponseInfo response_info_; + mojo::Receiver<network::mojom::URLLoader> receiver_{this}; + mojo::Remote<network::mojom::URLLoaderClient> client_; + scoped_refptr<net::HttpResponseHeaders> response_headers_; + base::WeakPtrFactory<ResourceBundleFileLoader> weak_factory_{this}; - mutable base::WeakPtrFactory<URLRequestResourceBundleJob> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(ResourceBundleFileLoader); }; } // namespace namespace extensions { +// Copied from chrome/browser/extensions/chrome_extensions_browser_api_provider.(h|cc) +class ChromeExtensionsBrowserAPIProvider : public ExtensionsBrowserAPIProvider +{ +public: + ChromeExtensionsBrowserAPIProvider() = default; + ~ChromeExtensionsBrowserAPIProvider() override = default; + + void RegisterExtensionFunctions(ExtensionFunctionRegistry *registry) override + { + // Generated APIs from Chrome. + api::ChromeGeneratedFunctionRegistry::RegisterAll(registry); + } + +private: + DISALLOW_COPY_AND_ASSIGN(ChromeExtensionsBrowserAPIProvider); +}; + +class QtWebEngineExtensionsBrowserAPIProvider : public ExtensionsBrowserAPIProvider +{ +public: + QtWebEngineExtensionsBrowserAPIProvider() = default; + ~QtWebEngineExtensionsBrowserAPIProvider() override = default; + + void RegisterExtensionFunctions(ExtensionFunctionRegistry *registry) override + { + // Generated APIs from QtWebEngine. + api::QtWebEngineGeneratedFunctionRegistry::RegisterAll(registry); + } + +private: + DISALLOW_COPY_AND_ASSIGN(QtWebEngineExtensionsBrowserAPIProvider); +}; + ExtensionsBrowserClientQt::ExtensionsBrowserClientQt() : api_client_(new ExtensionsAPIClientQt) , resource_manager_(new ComponentExtensionResourceManagerQt) { AddAPIProvider(std::make_unique<CoreExtensionsBrowserAPIProvider>()); - AddAPIProvider(std::make_unique<ExtensionsBrowserAPIProviderQt>()); + AddAPIProvider(std::make_unique<ChromeExtensionsBrowserAPIProvider>()); + AddAPIProvider(std::make_unique<QtWebEngineExtensionsBrowserAPIProvider>()); } ExtensionsBrowserClientQt::~ExtensionsBrowserClientQt() @@ -220,7 +335,7 @@ BrowserContext *ExtensionsBrowserClientQt::GetOriginalContext(BrowserContext *co bool ExtensionsBrowserClientQt::IsGuestSession(BrowserContext *context) const { - return false; + return context->IsOffTheRecord(); } bool ExtensionsBrowserClientQt::IsExtensionIncognitoEnabled(const std::string &extension_id, @@ -235,38 +350,6 @@ bool ExtensionsBrowserClientQt::CanExtensionCrossIncognito(const Extension *exte return false; } -net::URLRequestJob *ExtensionsBrowserClientQt::MaybeCreateResourceBundleRequestJob(net::URLRequest *request, - net::NetworkDelegate *network_delegate, - const base::FilePath &directory_path, - const std::string &content_security_policy, - bool send_cors_header) -{ - base::FilePath resources_path; - base::FilePath relative_path; - // Try to load extension resources from chrome resource file if - // directory_path is a descendant of resources_path. resources_path - // corresponds to src/chrome/browser/resources in source tree. - if (base::PathService::Get(base::DIR_QT_LIBRARY_DATA, &resources_path) && - // Since component extension resources are included in - // component_extension_resources.pak file in resources_path, calculate - // extension relative path against resources_path. - resources_path.AppendRelativePath(directory_path, &relative_path)) { - base::FilePath request_path = extensions::file_util::ExtensionURLToRelativeFilePath(request->url()); - int resource_id = 0; - if (GetComponentExtensionResourceManager()->IsComponentExtensionResource(directory_path, request_path, &resource_id)) { - relative_path = relative_path.Append(request_path); - relative_path = relative_path.NormalizePathSeparators(); - return new URLRequestResourceBundleJob(request, - network_delegate, - relative_path, - resource_id, - content_security_policy, - send_cors_header); - } - } - return nullptr; -} - // Return the resource relative path and id for the given request. base::FilePath ExtensionsBrowserClientQt::GetBundleResourcePath(const network::ResourceRequest &request, const base::FilePath &extension_resources_path, @@ -300,19 +383,20 @@ base::FilePath ExtensionsBrowserClientQt::GetBundleResourcePath(const network::R // Creates and starts a URLLoader to load an extension resource from the // embedder's resource bundle (.pak) files. Used for component extensions. void ExtensionsBrowserClientQt::LoadResourceFromResourceBundle(const network::ResourceRequest &request, - network::mojom::URLLoaderRequest loader, + mojo::PendingReceiver<network::mojom::URLLoader> loader, const base::FilePath &resource_relative_path, int resource_id, const std::string &content_security_policy, - network::mojom::URLLoaderClientPtr client, + mojo::PendingRemote<network::mojom::URLLoaderClient> client, bool send_cors_header) { - NOTIMPLEMENTED(); + ResourceBundleFileLoader::CreateAndStart(request, std::move(loader), std::move(client), resource_relative_path, + resource_id, content_security_policy, send_cors_header); } bool ExtensionsBrowserClientQt::AllowCrossRendererResourceLoad(const GURL &url, - content::ResourceType resource_type, + blink::mojom::ResourceType resource_type, ui::PageTransition page_transition, int child_id, bool is_incognito, @@ -320,10 +404,13 @@ bool ExtensionsBrowserClientQt::AllowCrossRendererResourceLoad(const GURL &url, const ExtensionSet &extensions, const ProcessMap &process_map) { - if (extension && extension->id() == extension_misc::kPdfExtensionId) return true; + // hangout services id + if (extension && extension->id() == "nkeimhogjdpnpccoofpliimaahmaaome") + return true; + bool allowed = false; if (url_request_util::AllowCrossRendererResourceLoad(url, resource_type, page_transition, child_id, @@ -352,9 +439,7 @@ ProcessManagerDelegate *ExtensionsBrowserClientQt::GetProcessManagerDelegate() c std::unique_ptr<ExtensionHostDelegate> ExtensionsBrowserClientQt::CreateExtensionHostDelegate() { - // TODO(extensions): Implement to support Apps. - NOTREACHED(); - return std::unique_ptr<ExtensionHostDelegate>(); + return std::unique_ptr<ExtensionHostDelegate>(new ExtensionHostDelegateQt); } bool ExtensionsBrowserClientQt::DidVersionUpdate(BrowserContext *context) @@ -382,17 +467,12 @@ ExtensionSystemProvider *ExtensionsBrowserClientQt::GetExtensionSystemFactory() return ExtensionSystemFactoryQt::GetInstance(); } -// void ExtensionsBrowserClientQt::RegisterExtensionFunctions(ExtensionFunctionRegistry *registry) const -//{ -// // Register core extension-system APIs. -// api::GeneratedFunctionRegistry::RegisterAll(registry); -//} - -void ExtensionsBrowserClientQt::RegisterExtensionInterfaces(service_manager::BinderRegistryWithArgs<content::RenderFrameHost *> *registry, - content::RenderFrameHost *render_frame_host, - const Extension *extension) const +void ExtensionsBrowserClientQt::RegisterBrowserInterfaceBindersForFrame( + mojo::BinderMapWithContext<content::RenderFrameHost*> *binder_map, + content::RenderFrameHost* render_frame_host, + const Extension* extension) const { - RegisterInterfacesForExtension(registry, render_frame_host, extension); + PopulateExtensionFrameBinders(binder_map, render_frame_host, extension); } std::unique_ptr<RuntimeAPIDelegate> ExtensionsBrowserClientQt::CreateRuntimeAPIDelegate(content::BrowserContext *context) const @@ -409,7 +489,7 @@ const ComponentExtensionResourceManager *ExtensionsBrowserClientQt::GetComponent void ExtensionsBrowserClientQt::BroadcastEventToRenderers(events::HistogramValue histogram_value, const std::string &event_name, - std::unique_ptr<base::ListValue> args) + std::unique_ptr<base::ListValue> args, bool dispatch_to_off_the_record_profiles) { NOTIMPLEMENTED(); // TODO : do the event routing diff --git a/src/core/extensions/extensions_browser_client_qt.h b/src/core/extensions/extensions_browser_client_qt.h index 41cb2ce20..5889694b7 100644 --- a/src/core/extensions/extensions_browser_client_qt.h +++ b/src/core/extensions/extensions_browser_client_qt.h @@ -47,6 +47,8 @@ #include "base/compiler_specific.h" #include "extensions/browser/extensions_browser_client.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/pending_remote.h" namespace extensions { @@ -73,13 +75,8 @@ public: bool IsGuestSession(content::BrowserContext *context) const override; bool IsExtensionIncognitoEnabled(const std::string &extension_id, content::BrowserContext *context) const override; bool CanExtensionCrossIncognito(const Extension *extension, content::BrowserContext *context) const override; - net::URLRequestJob *MaybeCreateResourceBundleRequestJob(net::URLRequest *request, - net::NetworkDelegate *network_delegate, - const base::FilePath &directory_path, - const std::string &content_security_policy, - bool send_cors_header) override; bool AllowCrossRendererResourceLoad(const GURL &url, - content::ResourceType resource_type, + blink::mojom::ResourceType resource_type, ui::PageTransition page_transition, int child_id, bool is_incognito, @@ -96,16 +93,16 @@ public: bool IsRunningInForcedAppMode() override; bool IsLoggedInAsPublicAccount() override; ExtensionSystemProvider *GetExtensionSystemFactory() override; -// void RegisterExtensionFunctions(ExtensionFunctionRegistry *registry) const; + void RegisterBrowserInterfaceBindersForFrame(mojo::BinderMapWithContext<content::RenderFrameHost*> *, + content::RenderFrameHost *, const extensions::Extension *) const override; + std::unique_ptr<RuntimeAPIDelegate> CreateRuntimeAPIDelegate(content::BrowserContext *context) const override; - void RegisterExtensionInterfaces(service_manager::BinderRegistryWithArgs<content::RenderFrameHost *> *registry, - content::RenderFrameHost *render_frame_host, - const Extension *extension) const override; const ComponentExtensionResourceManager * GetComponentExtensionResourceManager() override; void BroadcastEventToRenderers(events::HistogramValue histogram_value, const std::string &event_name, - std::unique_ptr<base::ListValue> args) override; + std::unique_ptr<base::ListValue> args, + bool dispatch_to_off_the_record_profiles) override; ExtensionCache *GetExtensionCache() override; bool IsBackgroundUpdateAllowed() override; bool IsMinBrowserVersionSupported(const std::string &min_version) override; @@ -126,11 +123,11 @@ public: // Creates and starts a URLLoader to load an extension resource from the // embedder's resource bundle (.pak) files. Used for component extensions. void LoadResourceFromResourceBundle(const network::ResourceRequest &request, - network::mojom::URLLoaderRequest loader, + mojo::PendingReceiver<network::mojom::URLLoader> loader, const base::FilePath &resource_relative_path, int resource_id, const std::string &content_security_policy, - network::mojom::URLLoaderClientPtr client, + mojo::PendingRemote<network::mojom::URLLoaderClient> client, bool send_cors_header) override; // Returns the locale used by the application. diff --git a/src/core/extensions/extensions_browser_api_provider_qt.cpp b/src/core/extensions/messaging_delegate_qt.cpp index 731dfb0fd..c666daa09 100644 --- a/src/core/extensions/extensions_browser_api_provider_qt.cpp +++ b/src/core/extensions/messaging_delegate_qt.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWebEngine module of the Qt Toolkit. @@ -37,18 +37,20 @@ ** ****************************************************************************/ -#include "extensions_browser_api_provider_qt.h" +#include "messaging_delegate_qt.h" -#include "extensions/browser/api/generated_api_registration.h" +#include <QtGlobal> namespace extensions { -ExtensionsBrowserAPIProviderQt::ExtensionsBrowserAPIProviderQt() = default; -ExtensionsBrowserAPIProviderQt::~ExtensionsBrowserAPIProviderQt() = default; -void ExtensionsBrowserAPIProviderQt::RegisterExtensionFunctions(ExtensionFunctionRegistry *registry) +MessagingDelegateQt::MessagingDelegateQt() { - api::GeneratedFunctionRegistry::RegisterAll(registry); } - +std::unique_ptr<base::DictionaryValue> MessagingDelegateQt::MaybeGetTabInfo(content::WebContents *web_contents) +{ + Q_UNUSED(web_contents); + return nullptr; } + +} // namespace extensions diff --git a/src/core/extensions/extensions_browser_api_provider_qt.h b/src/core/extensions/messaging_delegate_qt.h index f1d10ac95..44bfdc2d5 100644 --- a/src/core/extensions/extensions_browser_api_provider_qt.h +++ b/src/core/extensions/messaging_delegate_qt.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWebEngine module of the Qt Toolkit. @@ -37,26 +37,30 @@ ** ****************************************************************************/ -#ifndef EXTENSIONS_API_PROVIDER_QT_H -#define EXTENSIONS_API_PROVIDER_QT_H +#ifndef MESSAGING_DELEGATE_QT_H +#define MESSAGING_DELEGATE_QT_H -#include "extensions/browser/extensions_browser_api_provider.h" -#include "base/macros.h" +#include "extensions/browser/api/messaging/messaging_delegate.h" + +namespace base { +class DictionaryValue; +} + +namespace content { +class WebContents; +} namespace extensions { -class ExtensionsBrowserAPIProviderQt : public ExtensionsBrowserAPIProvider +class MessagingDelegateQt : public MessagingDelegate { public: - ExtensionsBrowserAPIProviderQt(); - ~ExtensionsBrowserAPIProviderQt() override; - - void RegisterExtensionFunctions(ExtensionFunctionRegistry *registry) override; + MessagingDelegateQt(); -private: - DISALLOW_COPY_AND_ASSIGN(ExtensionsBrowserAPIProviderQt); + // MessagingDelegate implementation. + std::unique_ptr<base::DictionaryValue> MaybeGetTabInfo(content::WebContents *web_contents) override; }; -} +} // namespace extensions -#endif // EXTENSIONS_API_PROVIDER_QT_H +#endif // MESSAGING_DELEGATE_QT_H diff --git a/src/core/extensions/mime_handler_view_guest_delegate_qt.cpp b/src/core/extensions/mime_handler_view_guest_delegate_qt.cpp index 022bc7db6..89d3d6f20 100644 --- a/src/core/extensions/mime_handler_view_guest_delegate_qt.cpp +++ b/src/core/extensions/mime_handler_view_guest_delegate_qt.cpp @@ -44,12 +44,17 @@ #include "mime_handler_view_guest_delegate_qt.h" -#include "content/browser/browser_plugin/browser_plugin_guest.h" -#include "content/browser/web_contents/web_contents_impl.h" +#include "content/public/browser/context_menu_params.h" #include "content/public/browser/web_contents.h" -#include "content/public/common/context_menu_params.h" #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h" +#include "profile_adapter.h" +#include "render_widget_host_view_qt.h" +#include "touch_selection_controller_client_qt.h" +#include "web_contents_adapter.h" +#include "web_contents_adapter_client.h" +#include "web_contents_view_qt.h" + namespace extensions { MimeHandlerViewGuestDelegateQt::MimeHandlerViewGuestDelegateQt(MimeHandlerViewGuest *) @@ -63,14 +68,17 @@ MimeHandlerViewGuestDelegateQt::~MimeHandlerViewGuestDelegateQt() bool MimeHandlerViewGuestDelegateQt::HandleContextMenu(content::WebContents *web_contents, const content::ContextMenuParams ¶ms) { - content::ContextMenuParams new_params = params; - - gfx::Point guest_coordinates = - static_cast<content::WebContentsImpl *>(web_contents)->GetBrowserPluginGuest()->GetScreenCoordinates(gfx::Point()); + content::WebContents *parent_web_contents = guest_view::GuestViewBase::GetTopLevelWebContents(web_contents); + if (auto rwhv = static_cast<QtWebEngineCore::RenderWidgetHostViewQt *>(parent_web_contents->GetRenderWidgetHostView())) { + if (rwhv->getTouchSelectionControllerClient()->handleContextMenu(params)) + return true; - // Adjust (x,y) position for offset from guest to embedder. - new_params.x += guest_coordinates.x(); - new_params.y += guest_coordinates.y(); + QtWebEngineCore::WebContentsAdapterClient *adapterClient = rwhv->adapterClient(); + QtWebEngineCore::WebEngineContextMenuData contextMenuData(QtWebEngineCore::WebContentsViewQt::buildContextMenuData(params)); + contextMenuData.setIsSpellCheckerEnabled(adapterClient->profileAdapter()->isSpellCheckEnabled()); + adapterClient->contextMenuRequested(contextMenuData); + return true; + } return false; } diff --git a/src/core/extensions/mime_handler_view_guest_delegate_qt.h b/src/core/extensions/mime_handler_view_guest_delegate_qt.h index 6cd80689c..8b2e29508 100644 --- a/src/core/extensions/mime_handler_view_guest_delegate_qt.h +++ b/src/core/extensions/mime_handler_view_guest_delegate_qt.h @@ -46,8 +46,7 @@ #define MIME_HANDLER_VIEW_GUEST_DELEGATE_QT_H_ #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest_delegate.h" -#include "content/browser/web_contents/web_contents_view.h" -#include "content/public/browser/web_contents.h" +#include "api/qtwebenginecoreglobal_p.h" namespace content { struct ContextMenuParams; diff --git a/src/core/extensions/pdf_iframe_navigation_throttle_qt.cpp b/src/core/extensions/pdf_iframe_navigation_throttle_qt.cpp new file mode 100644 index 000000000..7c2fe75f0 --- /dev/null +++ b/src/core/extensions/pdf_iframe_navigation_throttle_qt.cpp @@ -0,0 +1,219 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// based on //chrome/browser/plugins/pdf_iframe_navigation_throttle.cc +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +#include "extensions/pdf_iframe_navigation_throttle_qt.h" + +#include "chrome/grit/renderer_resources.h" +#include "components/strings/grit/components_strings.h" +#include "content/public/browser/download_utils.h" +#include "content/public/browser/navigation_handle.h" +#include "content/public/browser/plugin_service.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_user_data.h" +#include "content/public/common/webplugininfo.h" +#include "net/base/escape.h" +#include "net/http/http_response_headers.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/base/webui/jstemplate_builder.h" +#include "ui/base/webui/web_ui_util.h" + +namespace extensions { + +constexpr char kPDFMimeType[] = "application/pdf"; + +// Used to scope the posted navigation task to the lifetime of |web_contents|. +class PdfWebContentsLifetimeHelper : public content::WebContentsUserData<PdfWebContentsLifetimeHelper> +{ +public: + explicit PdfWebContentsLifetimeHelper(content::WebContents *web_contents) + : web_contents_(web_contents) + {} + + base::WeakPtr<PdfWebContentsLifetimeHelper> GetWeakPtr() + { + return weak_factory_.GetWeakPtr(); + } + + void NavigateIFrameToPlaceholder(const content::OpenURLParams &url_params) + { + web_contents_->OpenURL(url_params); + } + +private: + friend class content::WebContentsUserData<PdfWebContentsLifetimeHelper>; + + content::WebContents* const web_contents_; + base::WeakPtrFactory<PdfWebContentsLifetimeHelper> weak_factory_{this}; + + WEB_CONTENTS_USER_DATA_KEY_DECL(); +}; + +WEB_CONTENTS_USER_DATA_KEY_IMPL(PdfWebContentsLifetimeHelper) + +bool IsPDFPluginEnabled(content::NavigationHandle *navigation_handle, bool *is_stale) +{ + content::WebContents *web_contents = navigation_handle->GetWebContents(); + int process_id = web_contents->GetMainFrame()->GetProcess()->GetID(); + int routing_id = web_contents->GetMainFrame()->GetRoutingID(); + content::WebPluginInfo plugin_info; + // Will check WebEngineSettings by PluginServiceFilterQt + return content::PluginService::GetInstance()->GetPluginInfo( + process_id, routing_id, navigation_handle->GetURL(), + web_contents->GetMainFrame()->GetLastCommittedOrigin(), kPDFMimeType, + false /* allow_wildcard */, is_stale, &plugin_info, + nullptr /* actual_mime_type */); +} + +std::string GetPDFPlaceholderHTML(const GURL &pdf_url) +{ + std::string template_html = ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(IDR_PDF_PLUGIN_HTML); + webui::AppendWebUiCssTextDefaults(&template_html); + + base::DictionaryValue values; + values.SetString("fileName", pdf_url.ExtractFileName()); + values.SetString("open", l10n_util::GetStringUTF8(IDS_ACCNAME_OPEN)); + values.SetString("pdfUrl", pdf_url.spec()); + + return webui::GetI18nTemplateHtml(template_html, &values); +} + +// static +std::unique_ptr<content::NavigationThrottle> +PDFIFrameNavigationThrottleQt::MaybeCreateThrottleFor(content::NavigationHandle *handle) +{ + if (handle->IsInMainFrame()) + return nullptr; + return std::make_unique<PDFIFrameNavigationThrottleQt>(handle); +} + +PDFIFrameNavigationThrottleQt::PDFIFrameNavigationThrottleQt(content::NavigationHandle *handle) + : content::NavigationThrottle(handle) +{ +} + +PDFIFrameNavigationThrottleQt::~PDFIFrameNavigationThrottleQt() +{ +} + +content::NavigationThrottle::ThrottleCheckResult PDFIFrameNavigationThrottleQt::WillProcessResponse() +{ + const net::HttpResponseHeaders *response_headers = navigation_handle()->GetResponseHeaders(); + if (!response_headers) + return content::NavigationThrottle::PROCEED; + + std::string mime_type; + response_headers->GetMimeType(&mime_type); + if (mime_type != kPDFMimeType) + return content::NavigationThrottle::PROCEED; + + // We MUST download responses marked as attachments rather than showing + // a placeholder. + if (content::download_utils::MustDownload(navigation_handle()->GetURL(), response_headers, mime_type)) + return content::NavigationThrottle::PROCEED; + + bool is_stale = false; + bool pdf_plugin_enabled = IsPDFPluginEnabled(navigation_handle(), &is_stale); + + if (is_stale) { + // On browser start, the plugin list may not be ready yet. + content::PluginService::GetInstance()->GetPlugins( + base::BindOnce(&PDFIFrameNavigationThrottleQt::OnPluginsLoaded, + weak_factory_.GetWeakPtr())); + return content::NavigationThrottle::DEFER; + } + + // If the plugin was found, proceed on the navigation. Otherwise fall through + // to the placeholder case. + if (pdf_plugin_enabled) + return content::NavigationThrottle::PROCEED; + + LoadPlaceholderHTML(); + return content::NavigationThrottle::CANCEL_AND_IGNORE; +} + +const char *PDFIFrameNavigationThrottleQt::GetNameForLogging() +{ + return "PDFIFrameNavigationThrottleQt"; +} + +void PDFIFrameNavigationThrottleQt::OnPluginsLoaded( + const std::vector<content::WebPluginInfo> &plugins) +{ + if (IsPDFPluginEnabled(navigation_handle(), nullptr /* is_stale */)) { + Resume(); + } else { + LoadPlaceholderHTML(); + CancelDeferredNavigation(content::NavigationThrottle::CANCEL_AND_IGNORE); + } +} + +void PDFIFrameNavigationThrottleQt::LoadPlaceholderHTML() +{ + // Prepare the params to navigate to the placeholder. + std::string html = GetPDFPlaceholderHTML(navigation_handle()->GetURL()); + GURL data_url("data:text/html," + net::EscapePath(html)); + content::OpenURLParams params = content::OpenURLParams::FromNavigationHandle(navigation_handle()); + params.url = data_url; + params.transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME; + + // Post a task to navigate to the placeholder HTML. We don't navigate + // synchronously here, as starting a navigation within a navigation is + // an antipattern. Use a helper object scoped to the WebContents lifetime to + // scope the navigation task to the WebContents lifetime. + content::WebContents *web_contents = navigation_handle()->GetWebContents(); + if (!web_contents) + return; + + PdfWebContentsLifetimeHelper::CreateForWebContents(web_contents); + PdfWebContentsLifetimeHelper *helper = PdfWebContentsLifetimeHelper::FromWebContents(web_contents); + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&PdfWebContentsLifetimeHelper::NavigateIFrameToPlaceholder, + helper->GetWeakPtr(), std::move(params))); +} + +} // namespace extensions diff --git a/src/core/compositor/chromium_gpu_helper.h b/src/core/extensions/pdf_iframe_navigation_throttle_qt.h index 4086d12ab..37f5bf1d6 100644 --- a/src/core/compositor/chromium_gpu_helper.h +++ b/src/core/extensions/pdf_iframe_navigation_throttle_qt.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWebEngine module of the Qt Toolkit. @@ -37,53 +37,46 @@ ** ****************************************************************************/ -#ifndef CHROMIUM_GPU_HELPER_H -#define CHROMIUM_GPU_HELPER_H +// based on //chrome/browser/plugins/pdf_iframe_navigation_throttle.h +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -#include <QtGlobal> // We need this for the Q_OS_QNX define. +#ifndef PDF_IFRAME_NAVIGATION_THROTTLE_QT +#define PDF_IFRAME_NAVIGATION_THROTTLE_QT -#include "base/memory/scoped_refptr.h" +#include "content/public/browser/navigation_throttle.h" -namespace base { -class SingleThreadTaskRunner; -class TimeTicks; -} +#include "base/memory/weak_ptr.h" namespace content { -class RenderWidgetHost; -} - -namespace gpu { -struct Mailbox; -class MailboxManager; -class TextureBase; +class NavigationHandle; +struct WebPluginInfo; } -// These functions wrap code that needs to include headers that are -// incompatible with Qt GL headers. -// From the outside, types from incompatible headers referenced in these -// functions should only be forward-declared and considered as opaque types. - -scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner(); -gpu::MailboxManager *mailbox_manager(); +namespace extensions { -gpu::TextureBase* ConsumeTexture(gpu::MailboxManager *mailboxManager, unsigned target, const gpu::Mailbox& mailbox); -unsigned int service_id(gpu::TextureBase *tex); +// This class prevents automatical download of PDFs when they are embedded +// in subframes and plugins are disabled in API. +class PDFIFrameNavigationThrottleQt : public content::NavigationThrottle +{ +public: + static std::unique_ptr<content::NavigationThrottle> MaybeCreateThrottleFor(content::NavigationHandle *handle); -void ProgressFlingIfNeeded(content::RenderWidgetHost *host, const base::TimeTicks ¤t_time); + explicit PDFIFrameNavigationThrottleQt(content::NavigationHandle *handle); + ~PDFIFrameNavigationThrottleQt() override; -#ifdef Q_OS_QNX -typedef void* EGLDisplay; -typedef void* EGLStreamKHR; + // content::NavigationThrottle + content::NavigationThrottle::ThrottleCheckResult WillProcessResponse() override; + const char *GetNameForLogging() override; -struct EGLStreamData { - EGLDisplay egl_display; - EGLStreamKHR egl_str_handle; +private: + void OnPluginsLoaded(const std::vector<content::WebPluginInfo> &plugins); + void LoadPlaceholderHTML(); - EGLStreamData(): egl_display(NULL), egl_str_handle(NULL) {} + base::WeakPtrFactory<PDFIFrameNavigationThrottleQt> weak_factory_{this}; }; -EGLStreamData eglstream_connect_consumer(gpu::Texture *tex); -#endif +} // namespace extensions -#endif // CHROMIUM_GPU_HELPER_H +#endif // PDF_IFRAME_NAVIGATION_THROTTLE_QT diff --git a/src/core/extensions/plugin_service_filter_qt.cpp b/src/core/extensions/plugin_service_filter_qt.cpp new file mode 100644 index 000000000..b29dbbeab --- /dev/null +++ b/src/core/extensions/plugin_service_filter_qt.cpp @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "extensions/plugin_service_filter_qt.h" + +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/web_contents.h" + +#include "web_contents_delegate_qt.h" + +using namespace QtWebEngineCore; + +namespace extensions { + +// static +PluginServiceFilterQt *PluginServiceFilterQt::GetInstance() { + return base::Singleton<PluginServiceFilterQt>::get(); +} + +bool PluginServiceFilterQt::IsPluginAvailable(int render_process_id, + int render_frame_id, + const GURL &url, + const url::Origin &main_frame_origin, + content::WebPluginInfo *plugin) +{ + content::RenderFrameHost *frame_host = content::RenderFrameHost::FromID(render_process_id, render_frame_id); + content::WebContents *web_contents = content::WebContents::FromRenderFrameHost(frame_host); + if (!web_contents) { + // Availability checked somewhere before/during WebContents initialization. Let it load and enable + // all the plugins at this phase. This information will be queried again when receiving the response + // for the requested content. Postponing our decision and enabling/blocking there makes WebEngineSettings + // modifiable in runtime without reconstructing WebContents. + return true; + } + + if (web_contents->IsInnerWebContentsForGuest()) + web_contents = web_contents->GetOuterWebContents(); + + if (auto *delegate = static_cast<WebContentsDelegateQt *>(web_contents->GetDelegate())) { + const WebEngineSettings *settings = delegate->webEngineSettings(); + if (!settings->testAttribute(WebEngineSettings::PdfViewerEnabled) + || !settings->testAttribute(WebEngineSettings::PluginsEnabled)) + return false; + } + + return true; +} + +bool PluginServiceFilterQt::CanLoadPlugin(int render_process_id, + const base::FilePath &path) +{ + return true; +} + +PluginServiceFilterQt::PluginServiceFilterQt() +{ +} + +PluginServiceFilterQt::~PluginServiceFilterQt() +{ +} + +} // namespace extensions diff --git a/src/core/service/service_qt.h b/src/core/extensions/plugin_service_filter_qt.h index d4c89065c..ea5f082f2 100644 --- a/src/core/service/service_qt.h +++ b/src/core/extensions/plugin_service_filter_qt.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWebEngine module of the Qt Toolkit. @@ -37,39 +37,35 @@ ** ****************************************************************************/ -#ifndef SERVICE_QT_H -#define SERVICE_QT_H +#ifndef PLUGIN_SERVICE_FILTER_QT +#define PLUGIN_SERVICE_FILTER_QT -#include "base/no_destructor.h" -#include "content/public/common/service_manager_connection.h" +#include "content/public/browser/plugin_service_filter.h" -namespace service_manager { -class Connector; -class Service; -} // namespace service_manager +#include "base/memory/singleton.h" -class ServiceQt { -public: - static ServiceQt *GetInstance(); - - void InitConnector(); - content::ServiceManagerConnection::ServiceRequestHandler CreateServiceQtRequestHandler(); - service_manager::Connector *connector() { return m_connector.get(); } - -private: - friend class base::NoDestructor<ServiceQt>; - class IOThreadContext; +namespace extensions { - ServiceQt(); - ~ServiceQt(); +class PluginServiceFilterQt : public content::PluginServiceFilter { +public: + static PluginServiceFilterQt* GetInstance(); - void BindServiceQtRequest(service_manager::mojom::ServiceRequest request); + bool IsPluginAvailable(int render_process_id, + int render_frame_id, + const GURL &url, + const url::Origin &main_frame_origin, + content::WebPluginInfo *plugin) override; - const std::unique_ptr<IOThreadContext> m_ioThreadContext; + bool CanLoadPlugin(int render_process_id, + const base::FilePath &path) override; - std::unique_ptr<service_manager::Connector> m_connector; +private: + friend struct base::DefaultSingletonTraits<PluginServiceFilterQt>; - DISALLOW_COPY_AND_ASSIGN(ServiceQt); + PluginServiceFilterQt(); + ~PluginServiceFilterQt(); }; -#endif // SERVICE_QT_H +} // namespace extensions + +#endif // PLUGIN_SERVICE_FILTER_QT diff --git a/src/core/favicon_manager.cpp b/src/core/favicon_manager.cpp index a06da6769..4496606f9 100644 --- a/src/core/favicon_manager.cpp +++ b/src/core/favicon_manager.cpp @@ -52,6 +52,11 @@ #include "third_party/skia/include/core/SkPixelRef.h" #include "ui/gfx/geometry/size.h" +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +#include <qiconengine.h> +#include <private/qicon_p.h> +#endif + namespace QtWebEngineCore { static inline bool isResourceUrl(const QUrl &url) @@ -96,6 +101,7 @@ int FaviconManager::downloadIcon(const QUrl &url) id = m_webContents->DownloadImage( toGurl(url), true, // is_favicon + 0, // preferred_size maxSize, false, // normal cache policy base::Bind(&FaviconManager::iconDownloadFinished, m_weakFactory->GetWeakPtr())); @@ -330,6 +336,20 @@ QUrl FaviconManager::candidateIconUrl(bool touchIconsEnabled) const return iconUrl; } +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +static QPixmap getUnscaledPixmap(QIcon icon, const QSize &size) +{ + QPixmap pixmap = icon.data_ptr()->engine->pixmap(size, QIcon::Normal, QIcon::Off); + pixmap.setDevicePixelRatio(1.0); + return pixmap; +} +#else +static QPixmap getUnscaledPixmap(const QIcon &icon, const QSize &size) +{ + return icon.pixmap(size, 1.0); +} +#endif + void FaviconManager::generateCandidateIcon(bool touchIconsEnabled) { Q_ASSERT(m_candidateCount); @@ -348,7 +368,7 @@ void FaviconManager::generateCandidateIcon(bool touchIconsEnabled) if (!it->multiSize) { if (!m_candidateIcon.availableSizes().contains(it->size)) - m_candidateIcon.addPixmap(icon.pixmap(it->size)); + m_candidateIcon.addPixmap(getUnscaledPixmap(icon, it->size)); continue; } @@ -356,7 +376,7 @@ void FaviconManager::generateCandidateIcon(bool touchIconsEnabled) const auto sizes = icon.availableSizes(); for (const QSize &size : sizes) { if (!m_candidateIcon.availableSizes().contains(size)) - m_candidateIcon.addPixmap(icon.pixmap(size)); + m_candidateIcon.addPixmap(getUnscaledPixmap(icon, size)); } } } diff --git a/src/core/file_picker_controller.cpp b/src/core/file_picker_controller.cpp index 13e9437d2..22c18ec6f 100644 --- a/src/core/file_picker_controller.cpp +++ b/src/core/file_picker_controller.cpp @@ -39,9 +39,8 @@ #include "file_picker_controller.h" #include "type_conversion.h" -#if defined(OS_WIN) + #include "base/files/file_path.h" -#endif #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/file_select_listener.h" @@ -54,16 +53,32 @@ namespace QtWebEngineCore { -FilePickerController::FilePickerController(FileChooserMode mode, std::unique_ptr<content::FileSelectListener> listener, const QString &defaultFileName, const QStringList &acceptedMimeTypes, QObject *parent) +class FilePickerControllerPrivate { +public: + FilePickerController::FileChooserMode mode; + scoped_refptr<content::FileSelectListener> listener; + QString defaultFileName; + QStringList acceptedMimeTypes; +}; + +FilePickerController *createFilePickerController( + FilePickerController::FileChooserMode mode, scoped_refptr<content::FileSelectListener> listener, + const QString &defaultFileName, const QStringList &acceptedMimeTypes, QObject *parent = nullptr) +{ + auto priv = new FilePickerControllerPrivate{mode, listener, defaultFileName, acceptedMimeTypes}; + return new FilePickerController(priv, parent); +} + +FilePickerController::FilePickerController(FilePickerControllerPrivate *priv, QObject *parent) : QObject(parent) - , m_defaultFileName(defaultFileName) - , m_acceptedMimeTypes(acceptedMimeTypes) - , m_listener(std::move(listener)) - , m_mode(mode) + , d_ptr(priv) { } -FilePickerController::~FilePickerController() = default; +FilePickerController::~FilePickerController() +{ + delete d_ptr; +} void FilePickerController::accepted(const QStringList &files) { @@ -72,27 +87,64 @@ void FilePickerController::accepted(const QStringList &files) for (const QString &urlString : files) { // We accept strings on both absolute-path and file-URL form: - if (QDir::isAbsolutePath(urlString)) { - QString absolutePath = QDir::fromNativeSeparators(urlString); -#if defined(OS_WIN) - if (absolutePath.at(0).isLetter() && absolutePath.at(1) == QLatin1Char(':') && !base::FilePath::IsSeparator(absolutePath.at(2).toLatin1())) - qWarning("Ignoring invalid item in FilePickerController::accepted(QStringList): %s", qPrintable(urlString)); - else + if (toFilePath(urlString).IsAbsolute()) { + stringList.append(urlString); + continue; + } + + if (urlString.startsWith("file:")) { + base::FilePath filePath = toFilePath(urlString).NormalizePathSeparators(); + std::vector<base::FilePath::StringType> pathComponents; + // Splits the file URL into scheme, host name, path and file name. + filePath.GetComponents(&pathComponents); + + QString absolutePath; +#if !defined(OS_WIN) + absolutePath = "/"; #endif - stringList.append(absolutePath); - } else { - QUrl url(urlString, QUrl::StrictMode); - if (url.isLocalFile() && QDir::isAbsolutePath(url.toLocalFile())) { - QString absolutePath = url.toLocalFile(); + + QString scheme = toQt(pathComponents[0]); + if (scheme.size() > 5) { #if defined(OS_WIN) - if (absolutePath.at(0).isLetter() && absolutePath.at(1) == QLatin1Char(':') && !base::FilePath::IsSeparator(absolutePath.at(2).toLatin1())) + // There is no slash at the end of the file scheme and it is valid on Windows: file:C:/ + if (scheme.size() == 7 && scheme.at(5).isLetter() && scheme.at(6) == ':') { + absolutePath += scheme.at(5) + ":/"; + } else { +#endif qWarning("Ignoring invalid item in FilePickerController::accepted(QStringList): %s", qPrintable(urlString)); - else + continue; +#if defined(OS_WIN) + } +#endif + } + + // Non-local file and UNC Path validation: file://path/file + if (base::FilePath::IsSeparator(urlString.at(5).toLatin1()) + && base::FilePath::IsSeparator(urlString.at(6).toLatin1()) + && !base::FilePath::IsSeparator(urlString.at(7).toLatin1())) { +#if defined(OS_WIN) + if (urlString.at(8) != ':' && pathComponents.size() > 2) { + absolutePath += "//"; +#else + if (pathComponents.size() > 2) { + absolutePath += "/"; #endif - stringList.append(absolutePath); - } else - qWarning("Ignoring invalid item in FilePickerController::accepted(QStringList): %s", qPrintable(urlString)); + } else { + qWarning("Ignoring invalid item in FilePickerController::accepted(QStringList): %s", qPrintable(urlString)); + continue; + } + } + + // Build absolute path from file URI componenets. + for (size_t j = 1; j < pathComponents.size(); j++) + absolutePath += toQt(pathComponents[j]) + (j != pathComponents.size()-1 ? "/" : ""); + + if (toFilePath(absolutePath).IsAbsolute()) { + stringList.append(absolutePath); + continue; + } } + qWarning("Ignoring invalid item in FilePickerController::accepted(QStringList): %s", qPrintable(urlString)); } FilePickerController::filesSelectedInChooser(stringList); @@ -100,10 +152,19 @@ void FilePickerController::accepted(const QStringList &files) void FilePickerController::accepted(const QVariant &files) { - if (!files.canConvert(QVariant::StringList)) + QStringList stringList; + + if (files.canConvert(QVariant::StringList)) { + stringList = files.toStringList(); + } else if (files.canConvert<QList<QUrl> >()) { + const QList<QUrl> urls = files.value<QList<QUrl>>(); + for (const QUrl &url : urls) + stringList.append(url.toLocalFile()); + } else { qWarning("An unhandled type '%s' was provided in FilePickerController::accepted(QVariant)", files.typeName()); + } - accepted(files.toStringList()); + accepted(stringList); } void FilePickerController::rejected() @@ -133,9 +194,13 @@ ASSERT_ENUMS_MATCH(FilePickerController::Save, blink::mojom::FileChooserParams_M void FilePickerController::filesSelectedInChooser(const QStringList &filesList) { QStringList files(filesList); - if (this->m_mode == UploadFolder && !filesList.isEmpty() - && QFileInfo(filesList.first()).isDir()) // Enumerate the directory + base::FilePath baseDir; + if (d_ptr->mode == UploadFolder && !filesList.isEmpty() + && QFileInfo(filesList.first()).isDir()) { + // Enumerate the directory files = listRecursively(QDir(filesList.first())); + baseDir = toFilePath(filesList.first()); + } std::vector<blink::mojom::FileChooserFileInfoPtr> chooser_files; for (const auto &file : qAsConst(files)) { @@ -144,26 +209,26 @@ void FilePickerController::filesSelectedInChooser(const QStringList &filesList) } if (files.isEmpty()) - m_listener->FileSelectionCanceled(); + d_ptr->listener->FileSelectionCanceled(); else - m_listener->FileSelected(std::move(chooser_files), - /* FIXME? */ base::FilePath(), - static_cast<blink::mojom::FileChooserParams::Mode>(this->m_mode)); + d_ptr->listener->FileSelected(std::move(chooser_files), + baseDir, + static_cast<blink::mojom::FileChooserParams::Mode>(d_ptr->mode)); } QStringList FilePickerController::acceptedMimeTypes() const { - return m_acceptedMimeTypes; + return d_ptr->acceptedMimeTypes; } FilePickerController::FileChooserMode FilePickerController::mode() const { - return m_mode; + return d_ptr->mode; } QString FilePickerController::defaultFileName() const { - return m_defaultFileName; + return d_ptr->defaultFileName; } QStringList FilePickerController::nameFilters(const QStringList &acceptedMimeTypes) @@ -172,6 +237,9 @@ QStringList FilePickerController::nameFilters(const QStringList &acceptedMimeTyp QStringList acceptedGlobs; QMimeDatabase mimeDatabase; + if (acceptedMimeTypes.isEmpty()) + return nameFilters; + for (QString type : acceptedMimeTypes) { if (type.startsWith(".")) { // A single suffix diff --git a/src/core/file_picker_controller.h b/src/core/file_picker_controller.h index 0b680161a..0b84c889e 100644 --- a/src/core/file_picker_controller.h +++ b/src/core/file_picker_controller.h @@ -53,17 +53,12 @@ #include "qtwebenginecoreglobal_p.h" -#include <memory> - #include <QObject> #include <QStringList> -namespace content { - class FileSelectListener; -} - namespace QtWebEngineCore { +class FilePickerControllerPrivate; class Q_WEBENGINECORE_PRIVATE_EXPORT FilePickerController : public QObject { Q_OBJECT public: @@ -74,8 +69,9 @@ public: Save }; - FilePickerController(FileChooserMode mode, std::unique_ptr<content::FileSelectListener> listener, const QString &defaultFileName, const QStringList &acceptedMimeTypes, QObject * = 0); + FilePickerController(FilePickerControllerPrivate *priv, QObject *parent = nullptr); ~FilePickerController() override; + QStringList acceptedMimeTypes() const; QString defaultFileName() const; FileChooserMode mode() const; @@ -89,13 +85,9 @@ public Q_SLOTS: private: void filesSelectedInChooser(const QStringList &filesList); - QString m_defaultFileName; - QStringList m_acceptedMimeTypes; - std::unique_ptr<content::FileSelectListener> m_listener; - FileChooserMode m_mode; - + FilePickerControllerPrivate *d_ptr; }; -} // namespace +} // namespace QtWebEngineCore #endif // FILE_PICKER_CONTROLLER_H diff --git a/src/core/find_text_helper.cpp b/src/core/find_text_helper.cpp index da9d7f352..534e25862 100644 --- a/src/core/find_text_helper.cpp +++ b/src/core/find_text_helper.cpp @@ -97,18 +97,18 @@ void FindTextHelper::startFinding(const QString &findText, bool caseSensitively, void FindTextHelper::startFinding(const QString &findText, bool caseSensitively, bool findBackward) { - if (findText.isEmpty()) { - stopFinding(); - return; - } + Q_ASSERT(!findText.isEmpty()); - if (m_currentFindRequestId > m_lastCompletedFindRequestId) { + const bool findNext = !m_previousFindText.isEmpty() && findText == m_previousFindText; + if (isFindTextInProgress()) { // There are cases where the render process will overwrite a previous request // with the new search and we'll have a dangling callback, leaving the application // waiting for it forever. // Assume that any unfinished find has been unsuccessful when a new one is started // to cover that case. m_lastCompletedFindRequestId = m_currentFindRequestId; + if (!findNext) + m_webContents->StopFinding(content::STOP_FIND_ACTION_KEEP_SELECTION); m_viewClient->findTextFinished(QWebEngineFindTextResult()); invokeResultCallback(m_currentFindRequestId, 0); } @@ -116,7 +116,7 @@ void FindTextHelper::startFinding(const QString &findText, bool caseSensitively, blink::mojom::FindOptionsPtr options = blink::mojom::FindOptions::New(); options->forward = !findBackward; options->match_case = caseSensitively; - options->find_next = findText == m_previousFindText; + options->new_session = !findNext; m_previousFindText = findText; m_currentFindRequestId = m_findRequestIdCounter++; diff --git a/src/core/gn_run.pro b/src/core/gn_run.pro index 377d8363c..9f6e64504 100644 --- a/src/core/gn_run.pro +++ b/src/core/gn_run.pro @@ -4,7 +4,8 @@ QT_FOR_CONFIG += buildtools-private webenginecore-private core-private gui-priva TEMPLATE = aux -qtConfig(debug_and_release): CONFIG += debug_and_release build_all +qtConfig(debug_and_release): CONFIG += debug_and_release +qtConfig(build_all): CONFIG += build_all qtConfig(webengine-system-ninja) { QT_TOOL.ninja.binary = ninja @@ -27,36 +28,55 @@ build_pass|!debug_and_release { gn_binary = gn runninja.target = run_ninja + QMAKE_EXTRA_TARGETS += runninja - gn_args = $$gnArgs() + gn_args = $$gnWebEngineArgs() - gn_args += "qtwebengine_target=\"$$system_path($$OUT_PWD/$$getConfigDir()):QtWebEngineCore\"" !qtConfig(webengine-system-gn) { gn_binary = $$system_quote($$system_path($$gnPath())) } - gn_args = $$system_quote($$gn_args) gn_src_root = $$system_quote($$system_path($$QTWEBENGINE_ROOT/$$getChromiumSrcDir())) - gn_build_root = $$system_quote($$system_path($$OUT_PWD/$$getConfigDir())) gn_python = "--script-executable=$$pythonPathForSystem()" - gn_run = $$gn_binary gen $$gn_build_root $$gn_python --args=$$gn_args --root=$$gn_src_root - - message("Running: $$gn_run ") - !system($$gn_run) { - error("GN run error!") - } ninjaflags = $$(NINJAFLAGS) + enableThreads = $$(GN_MORE_THREADS) + isEmpty(enableThreads):macos { + gn_threads = "--threads=1" + } isEmpty(ninjaflags):!silent: ninjaflags = "-v" - - runninja.commands = $$NINJA $$ninjaflags \$\(NINJAJOBS\) -C $$gn_build_root QtWebEngineCore - QMAKE_EXTRA_TARGETS += runninja - build_pass:build_all: default_target.target = all else: default_target.target = first default_target.depends = runninja QMAKE_EXTRA_TARGETS += default_target + + isUniversal(){ + for(arch, QT_ARCHS) { + gn_target = "qtwebengine_target=\"$$system_path($$OUT_PWD/$$arch/$$getConfigDir()):QtWebEngineCore\"" + gn_args_per_arch = $$system_quote($$gn_args $$gn_target target_cpu=\"$$gnArch($$arch)\") + gn_build_root = $$system_quote($$system_path($$OUT_PWD/$$arch/$$getConfigDir())) + gn_run = $$gn_binary gen $$gn_build_root $$gn_python $$gn_threads --args=$$gn_args_per_arch --root=$$gn_src_root + message("Running for $$arch: $$gn_run") + !system($$gn_run) { + error("GN run error for $$arch!") + } + runninja_$${arch}.target = run_ninja_$${arch} + runninja_$${arch}.commands = $$NINJA $$ninjaflags \$\(NINJAJOBS\) -C $$gn_build_root QtWebEngineCore + QMAKE_EXTRA_TARGETS += runninja_$${arch} + runninja.depends += runninja_$${arch} + } + } else { + gn_args+= "qtwebengine_target=\"$$system_path($$OUT_PWD/$$getConfigDir()):QtWebEngineCore\"" + gn_args = $$system_quote($$gn_args) + gn_build_root = $$system_quote($$system_path($$OUT_PWD/$$getConfigDir())) + gn_run = $$gn_binary gen $$gn_build_root $$gn_python $$gn_threads --args=$$gn_args --root=$$gn_src_root + message("Running: $$gn_run") + !system($$gn_run) { + error("GN run error!") + } + runninja.commands = $$NINJA $$ninjaflags \$\(NINJAJOBS\) -C $$gn_build_root QtWebEngineCore + } } !build_pass:debug_and_release { @@ -64,3 +84,8 @@ build_pass|!debug_and_release { notParallel.target = .NOTPARALLEL QMAKE_EXTRA_TARGETS += notParallel } + +build_pass:CONFIG(debug, debug|release) { + TARGET = gn_run_debug +} + diff --git a/src/core/location_provider_qt.cpp b/src/core/location_provider_qt.cpp index d5a7f1297..94f6c6c9a 100644 --- a/src/core/location_provider_qt.cpp +++ b/src/core/location_provider_qt.cpp @@ -50,7 +50,6 @@ #include "base/bind.h" #include "base/memory/weak_ptr.h" -#include "base/message_loop/message_loop.h" #include "content/public/browser/browser_thread.h" #include "services/device/geolocation/geolocation_provider.h" #include "services/device/geolocation/geolocation_provider_impl.h" diff --git a/src/core/location_provider_qt.h b/src/core/location_provider_qt.h index 8e5ad0e54..db6b94e20 100644 --- a/src/core/location_provider_qt.h +++ b/src/core/location_provider_qt.h @@ -47,10 +47,6 @@ QT_FORWARD_DECLARE_CLASS(QThread) -namespace base { -class MessageLoop; -} - namespace QtWebEngineCore { class QtPositioningHelper; diff --git a/src/core/locked_ptr.h b/src/core/locked_ptr.h deleted file mode 100644 index 46d89819b..000000000 --- a/src/core/locked_ptr.h +++ /dev/null @@ -1,301 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef LOCKED_PTR_H -#define LOCKED_PTR_H - -#include <base/bind_internal.h> - -#include <QtCore/qreadwritelock.h> - -namespace base { - -struct LockedPtrCore -{ - LockedPtrCore(uintptr_t data) : data(data) {} - - std::atomic<size_t> refCount{1}; - // Atomic so that WeakLockedPtr::get can still read it. - std::atomic<uintptr_t> data; - QReadWriteLock lock{QReadWriteLock::Recursive}; -}; - -enum class LockedPtrMode { Weak, Shared, Exclusive }; - -template<class T, LockedPtrMode mode> class LockedPtr; - -// A WeakLockedPtr<T> is something like shared_ptr<T*>. The T* value can only be -// accessed by atomic read. -template<class T> using WeakLockedPtr = LockedPtr<T, LockedPtrMode::Weak>; - -// A SharedLockedPtr<T> is like WeakLockedPtr<T>, but the T* value is prevented -// from changing for the lifetime of the SharedLockedPtr by holding a -// shared-exclusive mutex in shared mode. -template<class T> using SharedLockedPtr = LockedPtr<T, LockedPtrMode::Shared>; - -// An ExclusiveLockedPtr<T> is like SharedLockedPtr<T>, but the mutex is held in -// exclusive mode. Only in this mode can the T* value be changed. -template<class T> using ExclusiveLockedPtr = LockedPtr<T, LockedPtrMode::Exclusive>; - -template<class T, LockedPtrMode mode> -class LockedPtr -{ - template<class T1> - static constexpr bool canConstructFrom = - std::is_same<T, T1>::value || - std::is_same<T, const T1>::value; - -public: - constexpr LockedPtr() {} - constexpr LockedPtr(std::nullptr_t) {} - - LockedPtr(const LockedPtr &that) - { - m_core = that.m_core; - lock(); - } - - LockedPtr &operator=(const LockedPtr &that) - { - unlock(); - m_core = that.m_core; - lock(); - } - - LockedPtr(LockedPtr &&that) - { - m_core = that.m_core; - that.m_core = nullptr; - } - - LockedPtr &operator=(LockedPtr &&that) - { - unlock(); - m_core = that.m_core; - that.m_core = nullptr; - } - - template<class T1, LockedPtrMode mode1, - class Enable = std::enable_if_t<canConstructFrom<T1>>> - LockedPtr(const LockedPtr<T1, mode1> &that) - { - m_core = that.m_core; - lock(); - } - - template<class T1, LockedPtrMode mode1, - class Enable = std::enable_if_t<canConstructFrom<T1>>> - LockedPtr &operator=(const LockedPtr<T1, mode1> &that) - { - unlock(); - m_core = that.m_core; - lock(); - } - - template<class T1, - class Enable = std::enable_if_t<canConstructFrom<T1>>> - LockedPtr(LockedPtr<T1, mode> &&that) - { - m_core = that.m_core; - that.m_core = nullptr; - } - - template<class T1, - class Enable = std::enable_if_t<canConstructFrom<T1>>> - LockedPtr &operator=(LockedPtr<T1, mode> &&that) - { - unlock(); - m_core = that.m_core; - that.m_core = nullptr; - } - - ~LockedPtr() - { - unlock(); - } - - T *get() const - { - if (m_core) { - if (mode == LockedPtrMode::Weak) - return reinterpret_cast<T *>(m_core->data.load(std::memory_order_acquire)); - else - return reinterpret_cast<T *>(m_core->data.load(std::memory_order_relaxed)); - } - return nullptr; - } - - void set(T *value) - { - static_assert(mode == LockedPtrMode::Exclusive, ""); - DCHECK(m_core); - m_core->data.store(reinterpret_cast<uintptr_t>(value), std::memory_order_release); - } - - T &operator*() const { return *get(); } - T *operator->() const { return get(); } - explicit operator bool() const { return get(); } - - bool MaybeValid() const { return m_core; } - - static LockedPtr create(T *value) - { - return new LockedPtrCore(reinterpret_cast<uintptr_t>(value)); - } - -private: - template<class T1, LockedPtrMode mode1> friend class LockedPtr; - - LockedPtr(LockedPtrCore *core) - : m_core(core) - {} - - void lock() - { - if (m_core) { - ++m_core->refCount; - - if (mode == LockedPtrMode::Shared) - m_core->lock.lockForRead(); - else if (mode == LockedPtrMode::Exclusive) - m_core->lock.lockForWrite(); - } - } - - void unlock() - { - if (m_core) { - if (mode != LockedPtrMode::Weak) - m_core->lock.unlock(); - - if (--m_core->refCount == 0) - delete m_core; - } - } - - LockedPtrCore *m_core = nullptr; -}; - -// This makes Bind check the pointer before calling the functor. -template<class T> -struct IsWeakReceiver<WeakLockedPtr<T>> : std::true_type {}; - -// By converting the WeakLockedPtr into a SharedLockedPtr we prevent the -// pointed-to object from being destroyed during the base::Callback::Run call. -// -// Unwrap() is called before checking the pointer, so there's no race condition. -template<class T> -struct BindUnwrapTraits<WeakLockedPtr<T>> -{ - static SharedLockedPtr<T> Unwrap(const WeakLockedPtr<T> &o) - { - return o; - } -}; - -// Like base::WeakPtrFactory, but InvalidateWeakPtrs *waits* until all currently -// executing base::Callbacks are finished. Queued up base::Callbacks are still -// canceled, exactly like with WeakPtrFactory. -// -// Consider, for example, the function -// -// void fun() -// { -// MyClass *myClass = new MyClass; -// myClass->scheduleDoStuff(); -// delete myClass; // ??? -// } -// -// where -// -// class MyClass -// { -// public: -// void scheduleDoStuff() -// { -// content::BrowserThread::PostTask( -// content::BrowserThread::IO, FROM_HERE, -// base::BindOnce(&MyClass::doStuff, m_weakPtrFactory.GetWeakPtr())); -// } -// void doStuff(); -// private: -// //base::WeakPtrFactory m_weakPtrFactory{this}; -// base::LockedPtrFactory m_weakPtrFactory{this}; -// }; -// -// What happens if the 'delete myClass' line is executed concurrently with -// MyClass::doStuff? -// -// With WeakPtrs we get a segfault or perhaps memory corruption. -// -// With LockedPtrs we get no crash and no corruption: LockedPtrFactory's -// destructor will wait until doStuff is done before continuing. -template<class T> -class LockedPtrFactory -{ -public: - explicit LockedPtrFactory(T *value) - : m_ptr(WeakLockedPtr<T>::create(value)) - {} - - ~LockedPtrFactory() - { - InvalidateWeakPtrs(); - } - - WeakLockedPtr<T> GetWeakPtr() { return m_ptr; } - WeakLockedPtr<const T> GetWeakPtr() const { return m_ptr; } - SharedLockedPtr<T> GetSharedPtr() { return m_ptr; } - SharedLockedPtr<const T> GetSharedPtr() const { return m_ptr; } - ExclusiveLockedPtr<T> GetExclusivePtr() { return m_ptr; } - ExclusiveLockedPtr<const T> GetExclusivePtr() const { return m_ptr; } - - void InvalidateWeakPtrs() - { - if (ExclusiveLockedPtr<T> ptr = m_ptr) - ptr.set(nullptr); - } - -private: - WeakLockedPtr<T> m_ptr; -}; - -} // namespace base - -#endif // !LOCKED_PTR_H diff --git a/src/core/login_delegate_qt.cpp b/src/core/login_delegate_qt.cpp index 80e2d9102..7942c8279 100644 --- a/src/core/login_delegate_qt.cpp +++ b/src/core/login_delegate_qt.cpp @@ -48,8 +48,6 @@ #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_view_host.h" -#include "content/public/browser/resource_dispatcher_host.h" -#include "content/public/browser/resource_request_info.h" #include "extensions/buildflags/buildflags.h" #include "services/network/public/cpp/features.h" @@ -84,16 +82,11 @@ LoginDelegateQt::LoginDelegateQt(const net::AuthChallengeInfo &authInfo, , m_auth_required_callback(std::move(auth_required_callback)) , m_weakFactory(this) { - base::PostTaskWithTraits( + base::PostTask( FROM_HERE, { content::BrowserThread::UI }, base::BindOnce(&LoginDelegateQt::triggerDialog, m_weakFactory.GetWeakPtr())); } -LoginDelegateQt::~LoginDelegateQt() -{ - destroy(); -} - QUrl LoginDelegateQt::url() const { return toQt(m_url); @@ -154,16 +147,6 @@ void LoginDelegateQt::sendAuthToRequester(bool success, const QString &user, con else std::move(m_auth_required_callback).Run(base::nullopt); } - - // With network service the auth callback has already deleted us. - if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) - destroy(); -} - -void LoginDelegateQt::destroy() -{ - m_dialogController.reset(); - m_auth_required_callback.Reset(); } } // namespace QtWebEngineCore diff --git a/src/core/login_delegate_qt.h b/src/core/login_delegate_qt.h index 20f302988..7b8d869e1 100644 --- a/src/core/login_delegate_qt.h +++ b/src/core/login_delegate_qt.h @@ -42,7 +42,6 @@ #include "content/public/browser/content_browser_client.h" #include "content/public/browser/login_delegate.h" -#include "content/public/browser/resource_request_info.h" #include "content/public/browser/web_contents_observer.h" #include "url/gurl.h" @@ -67,8 +66,6 @@ public: bool first_auth_attempt, LoginAuthRequiredCallback auth_required_callback); - ~LoginDelegateQt() override; - QUrl url() const; QString realm() const; QString host() const; @@ -79,7 +76,6 @@ public: private: void triggerDialog(); - void destroy(); net::AuthChallengeInfo m_authInfo; diff --git a/src/core/common/user_script_data.cpp b/src/core/macos_context_type_helper.h index 6f4b8cb05..d234a2bff 100644 --- a/src/core/common/user_script_data.cpp +++ b/src/core/macos_context_type_helper.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWebEngine module of the Qt Toolkit. @@ -36,14 +36,7 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ - -#include "user_script_data.h" -#include "base/pickle.h" - -UserScriptData::UserScriptData() : injectionPoint(AfterLoad) - , injectForSubframes(false) - , worldId(1) -{ - static uint64_t idCount = 0; - scriptId = idCount++; -} +#ifndef MACOS_CONTEXT_TYPE_HELPER_H_ +#define MACOS_CONTEXT_TYPE_HELPER_H_ +bool isCurrentContextSoftware(); +#endif // MACOS_CONTEXT_TYPE_HELPER_H_ diff --git a/src/core/command_line_pref_store_qt.h b/src/core/macos_context_type_helper.mm index a509f8ca9..c814d2849 100644 --- a/src/core/command_line_pref_store_qt.h +++ b/src/core/macos_context_type_helper.mm @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWebEngine module of the Qt Toolkit. @@ -36,21 +36,14 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#import <Foundation/Foundation.h> +#import <AppKit/AppKit.h> -#ifndef COMMAND_LINE_PREF_STORE_QT_H -#define COMMAND_LINE_PREF_STORE_QT_H +#include "macos_context_type_helper.h" -#include "base/command_line.h" -#include "components/prefs/command_line_pref_store.h" - -class CommandLinePrefStoreQt : public CommandLinePrefStore +bool isCurrentContextSoftware() { -public: - explicit CommandLinePrefStoreQt(const base::CommandLine *commandLine); - -protected: - ~CommandLinePrefStoreQt() override; - DISALLOW_COPY_AND_ASSIGN(CommandLinePrefStoreQt); -}; - -#endif // COMMAND_LINE_PREF_STORE_QT_H + int rendererID = 0; + [NSOpenGLContext.currentContext getValues:&rendererID forParameter:NSOpenGLContextParameterCurrentRendererID]; + return (rendererID & kCGLRendererIDMatchingMask) == kCGLRendererGenericFloatID; +} diff --git a/src/core/media_capture_devices_dispatcher.cpp b/src/core/media_capture_devices_dispatcher.cpp index 7bf499917..fc436cff2 100644 --- a/src/core/media_capture_devices_dispatcher.cpp +++ b/src/core/media_capture_devices_dispatcher.cpp @@ -59,9 +59,9 @@ #include "content/public/browser/notification_source.h" #include "content/public/browser/notification_types.h" #include "content/public/browser/render_process_host.h" -#include "content/public/common/origin_util.h" #include "media/audio/audio_device_description.h" #include "media/audio/audio_manager_base.h" +#include "third_party/blink/public/common/loader/network_utils.h" #include "ui/base/l10n/l10n_util.h" #if QT_CONFIG(webengine_webrtc) @@ -70,6 +70,13 @@ #endif #include <QtCore/qcoreapplication.h> +#include <QtCore/qscopeguard.h> + +#if defined(WEBRTC_USE_X11) +#include <dlfcn.h> +#include <X11/extensions/Xrandr.h> +#include <X11/Xlib.h> +#endif namespace QtWebEngineCore { @@ -117,25 +124,16 @@ void getDevicesForDesktopCapture(blink::MediaStreamDevices *devices, content::DesktopMediaID getDefaultScreenId() { - // While this function is executing another thread may also want to create a - // DesktopCapturer [1]. Unfortunately, creating a DesktopCapturer is not - // thread safe on X11 due to the use of webrtc::XErrorTrap. It's safe to - // disable this code on X11 since we don't actually need to create a - // DesktopCapturer to get the screen id anyway - // (ScreenCapturerLinux::GetSourceList always returns 0 as the id). - // - // [1]: webrtc::InProcessVideoCaptureDeviceLauncher::DoStartDesktopCaptureOnDeviceThread - -#if QT_CONFIG(webengine_webrtc) && !defined(WEBRTC_USE_X11) +#if QT_CONFIG(webengine_webrtc) // Source id patterns are different across platforms. - // On Linux, the hardcoded value "0" is used. + // On Linux and macOS, the source ids are randomish numbers assigned by the OS. // On Windows, the screens are enumerated consecutively in increasing order from 0. - // On macOS the source ids are randomish numbers assigned by the OS. // In order to provide a correct screen id, we query for the available screen ids, and // select the first one as the main display id. +#if !defined(WEBRTC_USE_X11) // The code is based on the file - // src/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc. + // chrome/browser/media/webrtc/native_desktop_media_list.cc. webrtc::DesktopCaptureOptions options = webrtc::DesktopCaptureOptions::CreateDefault(); options.set_disable_effects(false); @@ -150,7 +148,61 @@ content::DesktopMediaID getDefaultScreenId() } } } -#endif +#else + // This is a workaround to avoid thread issues with DesktopCapturer [1]. Unfortunately, + // creating a DesktopCapturer is not thread safe on X11 due to the use of webrtc::XErrorTrap. + // Can be removed if https://crbug.com/2022 and/or https://crbug.com/570852 are fixed. + // The code is based on the file + // third_party/webrtc/modules/desktop_capture/linux/screen_capturer_x11.cc. + // + // [1]: webrtc::InProcessVideoCaptureDeviceLauncher::DoStartDesktopCaptureOnDeviceThread + Display *display = XOpenDisplay(nullptr); + if (!display) { + qWarning("Unable to open display."); + return content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, 0); + } + + int randrEventBase = 0; + int errorBaseIgnored = 0; + if (!XRRQueryExtension(display, &randrEventBase, &errorBaseIgnored)) { + qWarning("X server does not support XRandR."); + return content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, 0); + } + + int majorVersion = 0; + int minorVersion = 0; + if (!XRRQueryVersion(display, &majorVersion, &minorVersion)) { + qWarning("X server does not support XRandR."); + return content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, 0); + } + + if (majorVersion < 1 || (majorVersion == 1 && minorVersion < 5)) { + qWarning("XRandR entension is older than v1.5."); + return content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, 0); + } + + typedef XRRMonitorInfo *(*GetMonitorsFunc)(Display *, Window, Bool, int *); + GetMonitorsFunc getMonitors = reinterpret_cast<GetMonitorsFunc>(dlsym(RTLD_DEFAULT, "XRRGetMonitors")); + typedef void (*FreeMonitorsFunc)(XRRMonitorInfo*); + FreeMonitorsFunc freeMonitors = reinterpret_cast<FreeMonitorsFunc>(dlsym(RTLD_DEFAULT, "XRRFreeMonitors")); + if (!getMonitors || !freeMonitors) { + qWarning("Unable to link XRandR monitor functions."); + return content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, 0); + } + + Window rootWindow = RootWindow(display, DefaultScreen(display)); + if (rootWindow == BadValue) { + qWarning("Unable to get the root window."); + return content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, 0); + } + + int numMonitors = 0; + XRRMonitorInfo *monitors = getMonitors(display, rootWindow, true, &numMonitors); + auto cleanup = qScopeGuard([&] () { freeMonitors(monitors); }); + if (numMonitors > 0) + return content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, monitors[0].name); +#endif // !defined(WEBRTC_USE_X11) +#endif // QT_CONFIG(webengine_webrtc) return content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, 0); } @@ -173,6 +225,10 @@ WebContentsAdapterClient::MediaRequestFlags mediaRequestFlagsForRequest(const co request.video_type == MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE) return {WebContentsAdapterClient::MediaDesktopAudioCapture, WebContentsAdapterClient::MediaDesktopVideoCapture}; + if (request.audio_type == MediaStreamType::DISPLAY_AUDIO_CAPTURE && + request.video_type == MediaStreamType::DISPLAY_VIDEO_CAPTURE) + return {WebContentsAdapterClient::MediaDesktopAudioCapture, WebContentsAdapterClient::MediaDesktopVideoCapture}; + if (request.video_type == MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE || request.video_type == MediaStreamType::DISPLAY_VIDEO_CAPTURE) return {WebContentsAdapterClient::MediaDesktopVideoCapture}; @@ -268,7 +324,8 @@ void MediaCaptureDevicesDispatcher::handleMediaAccessPermissionResponse(content: break; } } else if (desktopVideoRequested) { - getDevicesForDesktopCapture(&devices, getDefaultScreenId(), desktopAudioRequested, + bool captureAudio = desktopAudioRequested && m_loopbackAudioSupported; + getDevicesForDesktopCapture(&devices, getDefaultScreenId(), captureAudio, request.video_type, request.audio_type); } } @@ -280,9 +337,9 @@ void MediaCaptureDevicesDispatcher::handleMediaAccessPermissionResponse(content: // Post a task to process next queued request. It has to be done // asynchronously to make sure that calling infobar is not destroyed until // after this function returns. - base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, - base::BindOnce(&MediaCaptureDevicesDispatcher::ProcessQueuedAccessRequest, - base::Unretained(this), webContents)); + base::PostTask(FROM_HERE, {BrowserThread::UI}, + base::BindOnce(&MediaCaptureDevicesDispatcher::ProcessQueuedAccessRequest, + base::Unretained(this), webContents)); } if (devices.empty()) @@ -305,6 +362,10 @@ MediaCaptureDevicesDispatcher::MediaCaptureDevicesDispatcher() // content::NOTIFICATION_WEB_CONTENTS_DESTROYED, and that will result in // possible use after free. DCHECK_CURRENTLY_ON(BrowserThread::UI); +#if defined(OS_WIN) + // Currently loopback audio capture is supported only on Windows. + m_loopbackAudioSupported = true; +#endif m_notificationsRegistrar.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, content::NotificationService::AllSources()); } @@ -322,7 +383,7 @@ void MediaCaptureDevicesDispatcher::Observe(int type, const content::Notificatio } } -void MediaCaptureDevicesDispatcher::processMediaAccessRequest(WebContentsAdapterClient *adapterClient, content::WebContents *webContents, const content::MediaStreamRequest &request, content::MediaResponseCallback callback) +void MediaCaptureDevicesDispatcher::processMediaAccessRequest(content::WebContents *webContents, const content::MediaStreamRequest &request, content::MediaResponseCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -332,10 +393,13 @@ void MediaCaptureDevicesDispatcher::processMediaAccessRequest(WebContentsAdapter return; } + WebContentsDelegateQt *delegate = static_cast<WebContentsDelegateQt *>(webContents->GetDelegate()); + WebContentsAdapterClient *adapterClient = delegate->adapterClient(); + if (flags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture)) { const bool screenCaptureEnabled = adapterClient->webEngineSettings()->testAttribute(WebEngineSettings::ScreenCaptureEnabled); - const bool originIsSecure = content::IsOriginSecure(request.security_origin); + const bool originIsSecure = blink::network_utils::IsOriginSecure(request.security_origin); if (!screenCaptureEnabled || !originIsSecure) { std::move(callback).Run(blink::MediaStreamDevices(), MediaStreamRequestResult::INVALID_STATE, std::unique_ptr<content::MediaStreamUI>()); return; @@ -368,7 +432,7 @@ void MediaCaptureDevicesDispatcher::processDesktopCaptureAccessRequest(content:: // Resolve DesktopMediaID for the specified device id. mediaId = content::DesktopStreamsRegistry::GetInstance()->RequestMediaForStreamId( request.requested_video_device_id, main_frame->GetProcess()->GetID(), - main_frame->GetRoutingID(), request.security_origin, + main_frame->GetRoutingID(), url::Origin::Create(request.security_origin), &originalExtensionName, content::kRegistryStreamTypeDesktop); } @@ -379,9 +443,11 @@ void MediaCaptureDevicesDispatcher::processDesktopCaptureAccessRequest(content:: } // Audio is only supported for screen capture streams. - bool capture_audio = (mediaId.type == content::DesktopMediaID::TYPE_SCREEN && request.audio_type == MediaStreamType::GUM_DESKTOP_AUDIO_CAPTURE); + bool audioRequested = request.audio_type == MediaStreamType::GUM_DESKTOP_AUDIO_CAPTURE; + bool audioSupported = (mediaId.type == content::DesktopMediaID::TYPE_SCREEN && m_loopbackAudioSupported); + bool captureAudio = (audioRequested && audioSupported); - getDevicesForDesktopCapture(&devices, mediaId, capture_audio, request.video_type, request.audio_type); + getDevicesForDesktopCapture(&devices, mediaId, captureAudio, request.video_type, request.audio_type); if (devices.empty()) std::move(callback).Run(devices, MediaStreamRequestResult::INVALID_STATE, @@ -444,10 +510,10 @@ void MediaCaptureDevicesDispatcher::getDefaultDevices(const std::string &audioDe void MediaCaptureDevicesDispatcher::OnMediaRequestStateChanged(int render_process_id, int render_frame_id, int page_request_id, const GURL &security_origin, blink::mojom::MediaStreamType stream_type, content::MediaRequestState state) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, - base::BindOnce(&MediaCaptureDevicesDispatcher::updateMediaRequestStateOnUIThread, - base::Unretained(this), render_process_id, render_frame_id, - page_request_id, security_origin, stream_type, state)); + base::PostTask(FROM_HERE, {BrowserThread::UI}, + base::BindOnce(&MediaCaptureDevicesDispatcher::updateMediaRequestStateOnUIThread, + base::Unretained(this), render_process_id, render_frame_id, + page_request_id, security_origin, stream_type, state)); } void MediaCaptureDevicesDispatcher::updateMediaRequestStateOnUIThread(int render_process_id, diff --git a/src/core/media_capture_devices_dispatcher.h b/src/core/media_capture_devices_dispatcher.h index 6a67a53e9..2db457d33 100644 --- a/src/core/media_capture_devices_dispatcher.h +++ b/src/core/media_capture_devices_dispatcher.h @@ -66,7 +66,7 @@ class MediaCaptureDevicesDispatcher : public content::MediaObserver, public: static MediaCaptureDevicesDispatcher *GetInstance(); - void processMediaAccessRequest(WebContentsAdapterClient *, content::WebContents *, const content::MediaStreamRequest &, content::MediaResponseCallback); + void processMediaAccessRequest(content::WebContents *, const content::MediaStreamRequest &, content::MediaResponseCallback); // Called back from our WebContentsAdapter to grant the requested permission. void handleMediaAccessPermissionResponse(content::WebContents *, const QUrl &securityOrigin, WebContentsAdapterClient::MediaRequestFlags); @@ -127,6 +127,8 @@ private: content::NotificationRegistrar m_notificationsRegistrar; + bool m_loopbackAudioSupported = false; + DISALLOW_COPY_AND_ASSIGN(MediaCaptureDevicesDispatcher); }; diff --git a/src/core/net/client_cert_override.cpp b/src/core/net/client_cert_override.cpp index afb7ab5af..d768092e8 100644 --- a/src/core/net/client_cert_override.cpp +++ b/src/core/net/client_cert_override.cpp @@ -65,7 +65,7 @@ #include "net/ssl/client_cert_store_win.h" #endif -#if defined(OS_MACOSX) +#if defined(OS_MAC) #include "net/ssl/client_cert_store_mac.h" #endif @@ -83,7 +83,7 @@ public: std::move(private_key_callback).Run(m_key); } -#if defined(OS_MACOSX) +#if defined(OS_MAC) SecIdentityRef sec_identity_ref() const override { return nullptr; @@ -142,7 +142,7 @@ void ClientCertOverrideStore::GetClientCerts(const net::SSLCertRequestInfo &cert { #if QT_CONFIG(ssl) // Access the user-provided data from the UI thread, but return on whatever thread this is. - if (base::PostTaskWithTraitsAndReplyWithResult( + if (base::PostTaskAndReplyWithResult( FROM_HERE, { content::BrowserThread::UI }, base::BindOnce(&ClientCertOverrideStore::GetClientCertsOnUIThread, base::Unretained(this), std::cref(cert_request_info)), @@ -167,7 +167,7 @@ std::unique_ptr<net::ClientCertStore> ClientCertOverrideStore::createNativeStore return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreNSS(net::ClientCertStoreNSS::PasswordDelegateFactory())); #elif defined(OS_WIN) return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreWin()); -#elif defined(OS_MACOSX) +#elif defined(OS_MAC) return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreMac()); #else return nullptr; diff --git a/src/core/net/client_cert_store_data.cpp b/src/core/net/client_cert_store_data.cpp index 314e64145..a96e247b2 100644 --- a/src/core/net/client_cert_store_data.cpp +++ b/src/core/net/client_cert_store_data.cpp @@ -104,8 +104,8 @@ public: std::vector<uint16_t> GetAlgorithmPreferences() override { - return { SSL_SIGN_RSA_PKCS1_SHA1, SSL_SIGN_RSA_PKCS1_SHA512 - , SSL_SIGN_RSA_PKCS1_SHA384, SSL_SIGN_RSA_PKCS1_SHA256 }; + return net::SSLPrivateKey::DefaultAlgorithmPreferences(EVP_PKEY_id(m_key), + /* supports pss */ true); } std::string GetProviderName() override { return "qtwebengine"; diff --git a/src/core/net/cookie_monster_delegate_qt.cpp b/src/core/net/cookie_monster_delegate_qt.cpp index e0fa60be7..6d72a622b 100644 --- a/src/core/net/cookie_monster_delegate_qt.cpp +++ b/src/core/net/cookie_monster_delegate_qt.cpp @@ -61,10 +61,9 @@ public: ~CookieChangeListener() override = default; // network::mojom::CookieChangeListener: - void OnCookieChange(const net::CanonicalCookie &canonical_cookie, - network::mojom::CookieChangeCause cause) override + void OnCookieChange(const net::CookieChangeInfo &change) override { - m_delegate->OnCookieChanged(canonical_cookie, net::CookieChangeCause(cause)); + m_delegate->OnCookieChanged(change); } private: @@ -73,6 +72,25 @@ private: DISALLOW_COPY_AND_ASSIGN(CookieChangeListener); }; +class CookieAccessFilter : public network::mojom::CookieRemoteAccessFilter +{ +public: + CookieAccessFilter(CookieMonsterDelegateQt *delegate) : m_delegate(delegate) { } + ~CookieAccessFilter() override = default; + + void AllowedAccess(const GURL &url, const net::SiteForCookies &site_for_cookies, AllowedAccessCallback callback) override + { + bool allow = m_delegate->canGetCookies(toQt(site_for_cookies.first_party_url()), toQt(url)); + std::move(callback).Run(allow); + } + +private: + CookieMonsterDelegateQt *m_delegate; + + DISALLOW_COPY_AND_ASSIGN(CookieAccessFilter); +}; + + static GURL sourceUrlForCookie(const QNetworkCookie &cookie) { QString urlFragment = QStringLiteral("%1%2").arg(cookie.domain()).arg(cookie.path()); @@ -80,50 +98,37 @@ static GURL sourceUrlForCookie(const QNetworkCookie &cookie) } CookieMonsterDelegateQt::CookieMonsterDelegateQt() - : m_client(0) - , m_cookieMonster(nullptr) + : m_client(nullptr) , m_listener(new CookieChangeListener(this)) - , m_binding(m_listener.get()) + , m_filter(new CookieAccessFilter(this)) + , m_receiver(m_listener.get()) + , m_filterReceiver(m_filter.get()) + , m_hasFilter(false) { } CookieMonsterDelegateQt::~CookieMonsterDelegateQt() { - } void CookieMonsterDelegateQt::AddStore(net::CookieStore *store) { std::unique_ptr<net::CookieChangeSubscription> sub = store->GetChangeDispatcher().AddCallbackForAllChanges( - base::Bind(&CookieMonsterDelegateQt::OnCookieChanged, - // this object's destruction will deregister the subscription. - base::Unretained(this))); + base::BindRepeating(&CookieMonsterDelegateQt::OnCookieChanged, + // this object's destruction will deregister the subscription. + base::Unretained(this))); m_subscriptions.push_back(std::move(sub)); } bool CookieMonsterDelegateQt::hasCookieMonster() { - return m_cookieMonster || m_mojoCookieManager.is_bound(); + return m_mojoCookieManager.is_bound(); } void CookieMonsterDelegateQt::getAllCookies(quint64 callbackId) { - if (m_mojoCookieManager.is_bound()) { - m_mojoCookieManager->GetAllCookies(base::BindOnce(&CookieMonsterDelegateQt::GetAllCookiesCallbackOnUIThread, this, callbackId)); - } else { - net::CookieMonster::GetCookieListCallback callback = - base::BindOnce(&CookieMonsterDelegateQt::GetAllCookiesCallbackOnIOThread, this, callbackId); - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&CookieMonsterDelegateQt::GetAllCookiesOnIOThread, this, std::move(callback))); - } -} - -void CookieMonsterDelegateQt::GetAllCookiesOnIOThread(net::CookieMonster::GetCookieListCallback callback) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (m_cookieMonster) - m_cookieMonster->GetAllCookiesAsync(std::move(callback)); + m_mojoCookieManager->GetAllCookies(base::BindOnce(&CookieMonsterDelegateQt::GetAllCookiesCallbackOnUIThread, this, callbackId)); } void CookieMonsterDelegateQt::setCookie(quint64 callbackId, const QNetworkCookie &cookie, const QUrl &origin) @@ -136,31 +141,18 @@ void CookieMonsterDelegateQt::setCookie(quint64 callbackId, const QNetworkCookie GURL gurl = origin.isEmpty() ? sourceUrlForCookie(cookie) : toGurl(origin); std::string cookie_line = cookie.toRawForm().toStdString(); - if (m_mojoCookieManager.is_bound()) { - if (callbackId != CallbackDirectory::NoCallbackId) - callback = base::BindOnce(&CookieMonsterDelegateQt::SetCookieCallbackOnUIThread, this, callbackId); - net::CookieOptions options; - options.set_include_httponly(); - auto cookie = net::CanonicalCookie::Create(gurl, cookie_line, base::Time::Now(), options); - m_mojoCookieManager->SetCanonicalCookie(*cookie.get(), gurl.scheme(), options, std::move(callback)); - } else { - if (callbackId != CallbackDirectory::NoCallbackId) - callback = base::BindOnce(&CookieMonsterDelegateQt::SetCookieCallbackOnIOThread, this, callbackId); - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&CookieMonsterDelegateQt::SetCookieOnIOThread, this, - gurl, std::move(cookie_line), std::move(callback))); + if (callbackId != CallbackDirectory::NoCallbackId) + callback = base::BindOnce(&CookieMonsterDelegateQt::SetCookieCallbackOnUIThread, this, callbackId); + net::CookieInclusionStatus inclusion; + auto canonCookie = net::CanonicalCookie::Create(gurl, cookie_line, base::Time::Now(), base::nullopt, &inclusion); + if (!inclusion.IsInclude()) { + LOG(WARNING) << "QWebEngineCookieStore::setCookie() - Tried to set invalid cookie"; + return; } -} - -void CookieMonsterDelegateQt::SetCookieOnIOThread(const GURL &url, const std::string &cookie_line, - net::CookieMonster::SetCookiesCallback callback) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); net::CookieOptions options; options.set_include_httponly(); - - if (m_cookieMonster) - m_cookieMonster->SetCookieWithOptionsAsync(url, cookie_line, options, std::move(callback)); + options.set_same_site_cookie_context(net::CookieOptions::SameSiteCookieContext::MakeInclusiveForSet()); + m_mojoCookieManager->SetCanonicalCookie(*canonCookie.get(), gurl, options, std::move(callback)); } void CookieMonsterDelegateQt::deleteCookie(const QNetworkCookie &cookie, const QUrl &origin) @@ -170,69 +162,22 @@ void CookieMonsterDelegateQt::deleteCookie(const QNetworkCookie &cookie, const Q GURL gurl = origin.isEmpty() ? sourceUrlForCookie(cookie) : toGurl(origin); std::string cookie_name = cookie.name().toStdString(); - if (m_mojoCookieManager.is_bound()) { - auto filter = network::mojom::CookieDeletionFilter::New(); - filter->url = gurl; - filter->cookie_name = cookie_name; - m_mojoCookieManager->DeleteCookies(std::move(filter), network::mojom::CookieManager::DeleteCookiesCallback()); - } else { - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&CookieMonsterDelegateQt::DeleteCookieOnIOThread, this, - gurl, cookie_name)); - } -} - -void CookieMonsterDelegateQt::DeleteCookieOnIOThread(const GURL &url, const std::string &cookie_name) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (m_cookieMonster) { - net::CookieMonster::GetCookieListCallback callback = - base::BindOnce(&CookieMonsterDelegateQt::GetCookiesToDeleteCallback, this, cookie_name); - m_cookieMonster->GetAllCookiesForURLAsync(url, std::move(callback)); - } + auto filter = network::mojom::CookieDeletionFilter::New(); + filter->url = gurl; + filter->cookie_name = cookie_name; + m_mojoCookieManager->DeleteCookies(std::move(filter), network::mojom::CookieManager::DeleteCookiesCallback()); } -void CookieMonsterDelegateQt::GetCookiesToDeleteCallback(const std::string &cookie_name, const net::CookieList &cookies, - const net::CookieStatusList &statusList) -{ - Q_UNUSED(statusList); - if (!m_cookieMonster) - return; - - net::CookieList cookiesToDelete; - for (auto cookie : cookies) { - if (cookie.Name() == cookie_name) - cookiesToDelete.push_back(cookie); - } - for (auto cookie : cookiesToDelete) - m_cookieMonster->DeleteCanonicalCookieAsync(cookie, base::DoNothing()); -} - - void CookieMonsterDelegateQt::deleteSessionCookies(quint64 callbackId) { Q_ASSERT(hasCookieMonster()); Q_ASSERT(m_client); - if (m_mojoCookieManager.is_bound()) { - net::CookieMonster::DeleteCallback callback = - base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnUIThread, this, callbackId); - auto filter = network::mojom::CookieDeletionFilter::New(); - filter->session_control = network::mojom::CookieDeletionSessionControl::SESSION_COOKIES; - m_mojoCookieManager->DeleteCookies(std::move(filter), std::move(callback)); - } else { - net::CookieMonster::DeleteCallback callback = - base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnIOThread, this, callbackId); - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&CookieMonsterDelegateQt::DeleteSessionCookiesOnIOThread, this, std::move(callback))); - } -} - -void CookieMonsterDelegateQt::DeleteSessionCookiesOnIOThread(net::CookieMonster::DeleteCallback callback) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (m_cookieMonster) - m_cookieMonster->DeleteSessionCookiesAsync(std::move(callback)); + network::mojom::CookieManager::DeleteCookiesCallback callback = + base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnUIThread, this, callbackId); + auto filter = network::mojom::CookieDeletionFilter::New(); + filter->session_control = network::mojom::CookieDeletionSessionControl::SESSION_COOKIES; + m_mojoCookieManager->DeleteCookies(std::move(filter), std::move(callback)); } void CookieMonsterDelegateQt::deleteAllCookies(quint64 callbackId) @@ -240,63 +185,48 @@ void CookieMonsterDelegateQt::deleteAllCookies(quint64 callbackId) Q_ASSERT(hasCookieMonster()); Q_ASSERT(m_client); - if (m_mojoCookieManager.is_bound()) { - net::CookieMonster::DeleteCallback callback = - base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnUIThread, this, callbackId); - auto filter = network::mojom::CookieDeletionFilter::New(); - m_mojoCookieManager->DeleteCookies(std::move(filter), std::move(callback)); - } else { - net::CookieMonster::DeleteCallback callback = - base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnIOThread, this, callbackId); - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&CookieMonsterDelegateQt::DeleteAllOnIOThread, this, std::move(callback))); - } -} - -void CookieMonsterDelegateQt::DeleteAllOnIOThread(net::CookieMonster::DeleteCallback callback) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (m_cookieMonster) - m_cookieMonster->DeleteAllAsync(std::move(callback)); + network::mojom::CookieManager::DeleteCookiesCallback callback = + base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnUIThread, this, callbackId); + auto filter = network::mojom::CookieDeletionFilter::New(); + m_mojoCookieManager->DeleteCookies(std::move(filter), std::move(callback)); } -void CookieMonsterDelegateQt::setCookieMonster(net::CookieMonster *monster) +void CookieMonsterDelegateQt::setMojoCookieManager(network::mojom::CookieManagerPtrInfo cookie_manager_info) { - if (monster == m_cookieMonster) - return; + if (m_mojoCookieManager.is_bound()) + unsetMojoCookieManager(); - m_subscriptions.clear(); - if (monster) - AddStore(monster); + Q_ASSERT(!m_mojoCookieManager.is_bound()); + Q_ASSERT(!m_receiver.is_bound()); - m_cookieMonster = monster; + m_mojoCookieManager.Bind(std::move(cookie_manager_info)); - if (!m_client) - return; + m_mojoCookieManager->AddGlobalChangeListener(m_receiver.BindNewPipeAndPassRemote()); + if (m_hasFilter) + m_mojoCookieManager->SetRemoteFilter(m_filterReceiver.BindNewPipeAndPassRemote()); - if (monster) + if (m_client) m_client->d_func()->processPendingUserCookies(); - else - m_client->d_func()->rejectPendingUserCookies(); } -void CookieMonsterDelegateQt::setMojoCookieManager(network::mojom::CookieManagerPtrInfo cookie_manager_info) +void CookieMonsterDelegateQt::setHasFilter(bool hasFilter) { -// DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - m_mojoCookieManager.Bind(std::move(cookie_manager_info)); - - network::mojom::CookieChangeListenerPtr listener_ptr; - m_binding.Bind(mojo::MakeRequest(&listener_ptr)); - - m_mojoCookieManager->AddGlobalChangeListener(std::move(listener_ptr)); - - if (m_client) - m_client->d_func()->processPendingUserCookies(); + m_hasFilter = hasFilter; + if (!m_mojoCookieManager.is_bound()) + return; + if (m_hasFilter) { + if (!m_filterReceiver.is_bound()) + m_mojoCookieManager->SetRemoteFilter(m_filterReceiver.BindNewPipeAndPassRemote()); + } else { + if (m_filterReceiver.is_bound()) + m_filterReceiver.reset(); + } } void CookieMonsterDelegateQt::unsetMojoCookieManager() { - m_binding.Close(); + m_receiver.reset(); + m_filterReceiver.reset(); m_mojoCookieManager.reset(); } @@ -329,62 +259,24 @@ bool CookieMonsterDelegateQt::canGetCookies(const QUrl &firstPartyUrl, const QUr return m_client->d_func()->canAccessCookies(firstPartyUrl, url); } -void CookieMonsterDelegateQt::OnCookieChanged(const net::CanonicalCookie &cookie, net::CookieChangeCause cause) +void CookieMonsterDelegateQt::OnCookieChanged(const net::CookieChangeInfo &change) { if (!m_client) return; - m_client->d_func()->onCookieChanged(toQt(cookie), cause != net::CookieChangeCause::INSERTED); -} - -void CookieMonsterDelegateQt::GetAllCookiesCallbackOnIOThread(qint64 callbackId, const net::CookieList &cookies, const net::CookieStatusList &statusList) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - QByteArray rawCookies; - for (auto &&cookie : cookies) - rawCookies += toQt(cookie).toRawForm() % QByteArrayLiteral("\n"); - - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&CookieMonsterDelegateQt::GetAllCookiesResultOnUIThread, this, callbackId, rawCookies)); + m_client->d_func()->onCookieChanged(toQt(change.cookie), change.cause != net::CookieChangeCause::INSERTED); } -void CookieMonsterDelegateQt::GetAllCookiesCallbackOnUIThread(qint64 callbackId, const std::vector<net::CanonicalCookie> &cookies) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - QByteArray rawCookies; - for (auto &&cookie : cookies) - rawCookies += toQt(cookie).toRawForm() % QByteArrayLiteral("\n"); - - GetAllCookiesResultOnUIThread(callbackId, rawCookies); -} - -void CookieMonsterDelegateQt::SetCookieCallbackOnIOThread(qint64 callbackId, net::CanonicalCookie::CookieInclusionStatus status) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&CookieMonsterDelegateQt::SetCookieCallbackOnUIThread, this, callbackId, status)); -} - -void CookieMonsterDelegateQt::DeleteCookiesCallbackOnIOThread(qint64 callbackId, uint numCookies) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnUIThread, this, callbackId, numCookies)); -} - -void CookieMonsterDelegateQt::GetAllCookiesResultOnUIThread(qint64 callbackId, const QByteArray &cookies) +void CookieMonsterDelegateQt::GetAllCookiesCallbackOnUIThread(qint64 callbackId, const net::CookieList &cookies) { + QByteArray rawCookies = QByteArray::fromStdString(net::CanonicalCookie::BuildCookieLine(cookies)); if (m_client) - m_client->d_func()->onGetAllCallbackResult(callbackId, cookies); + m_client->d_func()->onGetAllCallbackResult(callbackId, rawCookies); } -void CookieMonsterDelegateQt::SetCookieCallbackOnUIThread(qint64 callbackId, net::CanonicalCookie::CookieInclusionStatus status) +void CookieMonsterDelegateQt::SetCookieCallbackOnUIThread(qint64 callbackId, net::CookieAccessResult status) { if (m_client) - m_client->d_func()->onSetCallbackResult(callbackId, - status == net::CanonicalCookie::CookieInclusionStatus::INCLUDE); + m_client->d_func()->onSetCallbackResult(callbackId, status.status.IsInclude()); } void CookieMonsterDelegateQt::DeleteCookiesCallbackOnUIThread(qint64 callbackId, uint numCookies) @@ -392,4 +284,5 @@ void CookieMonsterDelegateQt::DeleteCookiesCallbackOnUIThread(qint64 callbackId, if (m_client) m_client->d_func()->onDeleteCallbackResult(callbackId, numCookies); } -} + +} // namespace QtWebEngineCore diff --git a/src/core/net/cookie_monster_delegate_qt.h b/src/core/net/cookie_monster_delegate_qt.h index 02c84e061..fe1ed5be6 100644 --- a/src/core/net/cookie_monster_delegate_qt.h +++ b/src/core/net/cookie_monster_delegate_qt.h @@ -64,8 +64,9 @@ QT_WARNING_DISABLE_CLANG("-Wunused-parameter") #undef signals #endif #include "base/memory/ref_counted.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "net/cookies/cookie_monster.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "net/cookies/cookie_change_dispatcher.h" +#include "net/cookies/cookie_store.h" #include "services/network/public/mojom/cookie_manager.mojom-forward.h" #include "services/network/public/mojom/cookie_manager.mojom.h" #ifdef StAsH_signals @@ -81,23 +82,19 @@ QT_FORWARD_DECLARE_CLASS(QWebEngineCookieStore) namespace QtWebEngineCore { -// Extends net::CookieMonster::kDefaultCookieableSchemes with qrc, without enabling -// cookies for the file:// scheme, which is disabled by default in Chromium. -// Since qrc:// is similar to file:// and there are some unknowns about how -// to correctly handle file:// cookies, qrc:// should only be used for testing. -static const char *const kCookieableSchemes[] = { "http", "https", "qrc", "ws", "wss" }; - class CookieMonsterDelegateQtPrivate; class Q_WEBENGINECORE_PRIVATE_EXPORT CookieMonsterDelegateQt : public base::RefCountedThreadSafe<CookieMonsterDelegateQt> { QPointer<QWebEngineCookieStore> m_client; - net::CookieMonster *m_cookieMonster; std::vector<std::unique_ptr<net::CookieChangeSubscription>> m_subscriptions; network::mojom::CookieManagerPtr m_mojoCookieManager; std::unique_ptr<network::mojom::CookieChangeListener> m_listener; - mojo::Binding<network::mojom::CookieChangeListener> m_binding; + std::unique_ptr<network::mojom::CookieRemoteAccessFilter> m_filter; + mojo::Receiver<network::mojom::CookieChangeListener> m_receiver; + mojo::Receiver<network::mojom::CookieRemoteAccessFilter> m_filterReceiver; + bool m_hasFilter; public: CookieMonsterDelegateQt(); ~CookieMonsterDelegateQt(); @@ -110,35 +107,20 @@ public: void deleteSessionCookies(quint64 callbackId); void deleteAllCookies(quint64 callbackId); - void setCookieMonster(net::CookieMonster *monster); void setClient(QWebEngineCookieStore *client); void setMojoCookieManager(network::mojom::CookieManagerPtrInfo cookie_manager_info); void unsetMojoCookieManager(); + void setHasFilter(bool b); bool canSetCookie(const QUrl &firstPartyUrl, const QByteArray &cookieLine, const QUrl &url) const; bool canGetCookies(const QUrl &firstPartyUrl, const QUrl &url) const; void AddStore(net::CookieStore *store); - void OnCookieChanged(const net::CanonicalCookie &cookie, net::CookieChangeCause cause); + void OnCookieChanged(const net::CookieChangeInfo &change); private: - void GetAllCookiesOnIOThread(net::CookieMonster::GetCookieListCallback callback); - void SetCookieOnIOThread(const GURL &url, const std::string &cookie_line, - net::CookieMonster::SetCookiesCallback callback); - void DeleteCookieOnIOThread(const GURL &url, const std::string &cookie_name); - void DeleteSessionCookiesOnIOThread(net::CookieMonster::DeleteCallback callback); - void DeleteAllOnIOThread(net::CookieMonster::DeleteCallback callback); - - void GetCookiesToDeleteCallback(const std::string &cookie_name, const net::CookieList &cookies, - const net::CookieStatusList &statusList); - void GetAllCookiesCallbackOnIOThread(qint64 callbackId, const net::CookieList &cookies, - const net::CookieStatusList &statusList); - void SetCookieCallbackOnIOThread(qint64 callbackId, net::CanonicalCookie::CookieInclusionStatus status); - void DeleteCookiesCallbackOnIOThread(qint64 callbackId, uint numCookies); - - void GetAllCookiesCallbackOnUIThread(qint64 callbackId, const std::vector<net::CanonicalCookie> &cookies); - void GetAllCookiesResultOnUIThread(qint64 callbackId, const QByteArray &cookies); - void SetCookieCallbackOnUIThread(qint64 callbackId, net::CanonicalCookie::CookieInclusionStatus status); + void GetAllCookiesCallbackOnUIThread(qint64 callbackId, const net::CookieList &cookies); + void SetCookieCallbackOnUIThread(qint64 callbackId, net::CookieAccessResult status); void DeleteCookiesCallbackOnUIThread(qint64 callbackId, uint numCookies); }; diff --git a/src/core/net/custom_protocol_handler.cpp b/src/core/net/custom_protocol_handler.cpp deleted file mode 100644 index 7e8ee47ab..000000000 --- a/src/core/net/custom_protocol_handler.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "custom_protocol_handler.h" -#include "url_request_custom_job.h" - -#include "net/base/net_errors.h" -#include "net/url_request/url_request.h" -#include "net/url_request/url_request_error_job.h" - -namespace QtWebEngineCore { - -CustomProtocolHandler::CustomProtocolHandler(QPointer<ProfileAdapter> profileAdapter) - : m_profileAdapter(profileAdapter) -{ -} - -net::URLRequestJob *CustomProtocolHandler::MaybeCreateJob(net::URLRequest *request, net::NetworkDelegate *networkDelegate) const -{ - if (!networkDelegate) - return new net::URLRequestErrorJob(request, nullptr, net::ERR_ACCESS_DENIED); - - return new URLRequestCustomJob(request, networkDelegate, request->url().scheme(), m_profileAdapter); -} - -} // namespace diff --git a/src/core/net/custom_url_loader_factory.cpp b/src/core/net/custom_url_loader_factory.cpp index a9e7e1c34..c7426a5b9 100644 --- a/src/core/net/custom_url_loader_factory.cpp +++ b/src/core/net/custom_url_loader_factory.cpp @@ -43,14 +43,18 @@ #include "base/task/post_task.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" -#include "mojo/public/cpp/bindings/binding_set.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/receiver_set.h" #include "mojo/public/cpp/system/data_pipe.h" -#include "mojo/public/cpp/system/data_pipe_producer.h" +#include "mojo/public/cpp/system/simple_watcher.h" #include "net/base/net_errors.h" #include "net/http/http_status_code.h" #include "net/http/http_util.h" +#include "services/network/public/cpp/cors/cors.h" #include "services/network/public/mojom/url_loader.mojom.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" +#include "services/network/public/mojom/url_response_head.mojom.h" #include "api/qwebengineurlscheme.h" #include "net/url_request_custom_job_proxy.h" @@ -87,27 +91,29 @@ public: // network::mojom::URLLoader: void FollowRedirect(const std::vector<std::string> &removed_headers, const net::HttpRequestHeaders &modified_headers, + const net::HttpRequestHeaders &modified_cors_exempt_headers, // FIXME: do something with this? const base::Optional<GURL> &new_url) override { // We can be asked for follow our own redirect scoped_refptr<URLRequestCustomJobProxy> proxy = new URLRequestCustomJobProxy(this, m_proxy->m_scheme, m_proxy->m_profileAdapter); m_proxy->m_client = nullptr; // m_taskRunner->PostTask(FROM_HERE, base::BindOnce(&URLRequestCustomJobProxy::release, m_proxy)); - base::PostTaskWithTraits(FROM_HERE, { content::BrowserThread::UI }, - base::BindOnce(&URLRequestCustomJobProxy::release, m_proxy)); + base::PostTask(FROM_HERE, { content::BrowserThread::UI }, + base::BindOnce(&URLRequestCustomJobProxy::release, m_proxy)); m_proxy = std::move(proxy); if (new_url) m_request.url = *new_url; else m_request.url = m_redirect; - // ### remove and modify headers? m_redirect = GURL(); + for (const std::string &header: removed_headers) + m_request.headers.RemoveHeader(header); + m_request.headers.MergeFrom(modified_headers); Start(); } void SetPriority(net::RequestPriority priority, int32_t intra_priority_value) override { } void PauseReadingBodyFromNet() override { } void ResumeReadingBodyFromNet() override { } - void ProceedWithResponse() override { } private: CustomURLLoader(const network::ResourceRequest &request, @@ -121,8 +127,10 @@ private: , m_client(std::move(client_info)) , m_request(request) { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); m_binding.set_connection_error_handler( - base::BindOnce(&CustomURLLoader::OnConnectionError, base::Unretained(this))); + base::BindOnce(&CustomURLLoader::OnConnectionError, m_weakPtrFactory.GetWeakPtr())); + m_firstBytePosition = 0; m_device = nullptr; m_error = 0; QWebEngineUrlScheme scheme = QWebEngineUrlScheme::schemeByName(QByteArray::fromStdString(request.url.scheme())); @@ -133,7 +141,20 @@ private: void Start() { - m_head.request_start = base::TimeTicks::Now(); + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + + if (network::cors::IsCorsEnabledRequestMode(m_request.mode)) { + // CORS mode requires a valid request_initiator. + if (!m_request.request_initiator) + return CompleteWithFailure(net::ERR_INVALID_ARGUMENT); + + // Custom schemes are not covered by CorsURLLoader, so we need to reject CORS requests manually. + if (!m_corsEnabled && !m_request.request_initiator->IsSameOriginWith(url::Origin::Create(m_request.url))) + return CompleteWithFailure(network::CorsErrorStatus(network::mojom::CorsError::kCorsDisabledScheme)); + } + + m_head = network::mojom::URLResponseHead::New(); + m_head->request_start = base::TimeTicks::Now(); if (!m_pipe.consumer_handle.is_valid()) return CompleteWithFailure(net::ERR_FAILED); @@ -145,20 +166,33 @@ private: if (!m_request.referrer.is_empty()) headers.emplace("Referer", m_request.referrer.spec()); + std::string rangeHeader; + if (ParseRange(m_request.headers)) + m_firstBytePosition = m_byteRange.first_byte_position(); + // m_taskRunner->PostTask(FROM_HERE, - base::PostTaskWithTraits(FROM_HERE, { content::BrowserThread::UI }, - base::BindOnce(&URLRequestCustomJobProxy::initialize, m_proxy, - m_request.url, m_request.method, m_request.request_initiator, std::move(headers))); + base::PostTask(FROM_HERE, { content::BrowserThread::UI }, + base::BindOnce(&URLRequestCustomJobProxy::initialize, m_proxy, + m_request.url, m_request.method, m_request.request_initiator, std::move(headers))); + } + + void CompleteWithFailure(network::CorsErrorStatus cors_error) + { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + m_client->OnComplete(network::URLLoaderCompletionStatus(cors_error)); + ClearProxyAndClient(false); } void CompleteWithFailure(net::Error net_error) { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); m_client->OnComplete(network::URLLoaderCompletionStatus(net_error)); ClearProxyAndClient(false); } void OnConnectionError() { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); m_binding.Close(); if (m_client.is_bound()) ClearProxyAndClient(false); @@ -168,9 +202,10 @@ private: void OnTransferComplete(MojoResult result) { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); if (result == MOJO_RESULT_OK) { network::URLLoaderCompletionStatus status(net::OK); - status.encoded_data_length = m_totalBytesRead + m_head.headers->raw_headers().length(); + status.encoded_data_length = m_totalBytesRead + m_headerBytesRead; status.encoded_body_length = m_totalBytesRead; status.decoded_body_length = m_totalBytesRead; m_client->OnComplete(status); @@ -182,14 +217,15 @@ private: void ClearProxyAndClient(bool wait_for_loader_error = false) { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); m_proxy->m_client = nullptr; m_client.reset(); if (m_device && m_device->isOpen()) m_device->close(); m_device = nullptr; // m_taskRunner->PostTask(FROM_HERE, base::BindOnce(&URLRequestCustomJobProxy::release, m_proxy)); - base::PostTaskWithTraits(FROM_HERE, { content::BrowserThread::UI }, - base::BindOnce(&URLRequestCustomJobProxy::release, m_proxy)); + base::PostTask(FROM_HERE, { content::BrowserThread::UI }, + base::BindOnce(&URLRequestCustomJobProxy::release, m_proxy)); if (!wait_for_loader_error || !m_binding.is_bound()) delete this; } @@ -197,26 +233,44 @@ private: // URLRequestCustomJobProxy::Client: void notifyExpectedContentSize(qint64 size) override { - m_head.content_length = size; + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + m_totalSize = size; + if (m_byteRange.IsValid()) { + if (!m_byteRange.ComputeBounds(size)) { + CompleteWithFailure(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); + } else { + m_maxBytesToRead = m_byteRange.last_byte_position() - m_byteRange.first_byte_position() + 1; + m_head->content_length = m_maxBytesToRead; + } + } else { + m_head->content_length = size; + } } void notifyHeadersComplete() override { - m_taskRunner->PostTask(FROM_HERE, - base::BindOnce(&CustomURLLoader::reportHeadersComplete, base::Unretained(this))); - } - void reportHeadersComplete() - { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); DCHECK(!m_error); - m_head.response_start = base::TimeTicks::Now(); + m_head->response_start = base::TimeTicks::Now(); std::string headers; if (!m_redirect.is_empty()) { headers += "HTTP/1.1 303 See Other\n"; headers += base::StringPrintf("Location: %s\n", m_redirect.spec().c_str()); } else { - headers += "HTTP/1.1 200 OK\n"; + if (m_byteRange.IsValid() && m_totalSize > 0) { + headers += "HTTP/1.1 206 Partial Content\n"; + headers += net::HttpResponseHeaders::kContentRange; + headers += base::StringPrintf(": bytes %lld-%lld/%lld", + qlonglong{m_byteRange.first_byte_position()}, + qlonglong{m_byteRange.last_byte_position()}, + qlonglong{m_totalSize}); + headers += "\n"; + } else { + headers += "HTTP/1.1 200 OK\n"; + } if (m_mimeType.size() > 0) { - headers += base::StringPrintf("Content-Type: %s", m_mimeType.c_str()); + headers += net::HttpRequestHeaders::kContentType; + headers += base::StringPrintf(": %s", m_mimeType.c_str()); if (m_charset.size() > 0) headers += base::StringPrintf("; charset=%s", m_charset.c_str()); headers += "\n"; @@ -229,43 +283,56 @@ private: headers += "Access-Control-Allow-Credentials: true\n"; } } - m_head.headers = base::MakeRefCounted<net::HttpResponseHeaders>(net::HttpUtil::AssembleRawHeaders(headers)); - m_head.encoded_data_length = m_head.headers->raw_headers().length(); + m_head->headers = base::MakeRefCounted<net::HttpResponseHeaders>(net::HttpUtil::AssembleRawHeaders(headers)); + m_head->encoded_data_length = m_head->headers->raw_headers().length(); if (!m_redirect.is_empty()) { - m_head.content_length = m_head.encoded_body_length = -1; - net::URLRequest::FirstPartyURLPolicy first_party_url_policy = - m_request.update_first_party_url_on_redirect ? net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT - : net::URLRequest::NEVER_CHANGE_FIRST_PARTY_URL; + m_head->content_length = m_head->encoded_body_length = -1; + net::RedirectInfo::FirstPartyURLPolicy first_party_url_policy = + m_request.update_first_party_url_on_redirect ? net::RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT + : net::RedirectInfo::FirstPartyURLPolicy::NEVER_CHANGE_URL; net::RedirectInfo redirectInfo = net::RedirectInfo::ComputeRedirectInfo( m_request.method, m_request.url, - m_request.site_for_cookies, m_request.top_frame_origin, + m_request.site_for_cookies, first_party_url_policy, m_request.referrer_policy, m_request.referrer.spec(), net::HTTP_SEE_OTHER, m_redirect, base::nullopt, false /*insecure_scheme_was_upgraded*/); - m_client->OnReceiveRedirect(redirectInfo, m_head); + m_client->OnReceiveRedirect(redirectInfo, std::move(m_head)); + m_head = nullptr; // ### should m_request be updated with RedirectInfo? (see FollowRedirect) return; } DCHECK(m_device); - m_head.mime_type = m_mimeType; - m_head.charset = m_charset; - m_client->OnReceiveResponse(m_head); + m_head->mime_type = m_mimeType; + m_head->charset = m_charset; + m_headerBytesRead = m_head->headers->raw_headers().length(); + m_client->OnReceiveResponse(std::move(m_head)); m_client->OnStartLoadingResponseBody(std::move(m_pipe.consumer_handle)); + m_head = nullptr; - readAvailableData(); + m_watcher = std::make_unique<mojo::SimpleWatcher>( + FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL, m_taskRunner); + m_watcher->Watch(m_pipe.producer_handle.get(), MOJO_HANDLE_SIGNAL_WRITABLE, + MOJO_WATCH_CONDITION_SATISFIED, + base::BindRepeating(&CustomURLLoader::notifyReadyWrite, + m_weakPtrFactory.GetWeakPtr())); + + readAvailableData(); // May delete this } void notifyCanceled() override { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); OnTransferComplete(MOJO_RESULT_CANCELLED); } void notifyAborted() override { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); notifyStartFailure(net::ERR_ABORTED); } void notifyStartFailure(int error) override { - m_head.response_start = base::TimeTicks::Now(); + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + m_head->response_start = base::TimeTicks::Now(); std::string headers; switch (error) { case net::ERR_INVALID_URL: @@ -287,83 +354,128 @@ private: headers = "HTTP/1.1 500 Internal Error\n"; break; } - m_head.headers = base::MakeRefCounted<net::HttpResponseHeaders>(net::HttpUtil::AssembleRawHeaders(headers)); - m_head.encoded_data_length = m_head.headers->raw_headers().length(); - m_head.content_length = m_head.encoded_body_length = -1; - m_client->OnReceiveResponse(m_head); + m_head->headers = base::MakeRefCounted<net::HttpResponseHeaders>(net::HttpUtil::AssembleRawHeaders(headers)); + m_head->encoded_data_length = m_head->headers->raw_headers().length(); + m_head->content_length = m_head->encoded_body_length = -1; + m_client->OnReceiveResponse(std::move(m_head)); CompleteWithFailure(net::Error(error)); } void notifyReadyRead() override { - m_taskRunner->PostTask(FROM_HERE, - base::BindOnce(&CustomURLLoader::readAvailableData, base::Unretained(this))); + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + readAvailableData(); } - void readAvailableData() + void notifyReadyWrite(MojoResult result, const mojo::HandleSignalsState &state) { - if (m_error) { - CompleteWithFailure(net::Error(m_error)); - return; - } - if (!m_device) { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + if (result != MOJO_RESULT_OK) { CompleteWithFailure(net::ERR_FAILED); return; } - char buffer[2048]; - do { - int read_size = m_device->read(buffer, 2048); - if (m_error) { - CompleteWithFailure(net::Error(m_error)); - return; + readAvailableData(); + } + bool readAvailableData() + { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + for (;;) { + if (m_error || !m_device) + break; + + void *buffer = nullptr; + uint32_t bufferSize = 0; + MojoResult beginResult = m_pipe.producer_handle->BeginWriteData( + &buffer, &bufferSize, MOJO_BEGIN_WRITE_DATA_FLAG_NONE); + if (beginResult == MOJO_RESULT_SHOULD_WAIT) { + m_watcher->ArmOrNotify(); + return false; // Wait for pipe watcher } - if (read_size > 0) { - uint32_t read_bytes = read_size; - m_pipe.producer_handle->WriteData(buffer, &read_bytes, MOJO_WRITE_DATA_FLAG_NONE); - m_totalBytesRead += read_bytes; - } else if (read_size < 0 && !m_device->atEnd()) { - CompleteWithFailure(net::ERR_FAILED); - return; + if (beginResult != MOJO_RESULT_OK) + break; + if (m_maxBytesToRead > 0 && m_maxBytesToRead <= int64_t{std::numeric_limits<uint32_t>::max()}) + bufferSize = std::min(bufferSize, uint32_t(m_maxBytesToRead)); + + int readResult = m_device->read(static_cast<char *>(buffer), bufferSize); + uint32_t bytesRead = std::max(readResult, 0); + m_pipe.producer_handle->EndWriteData(bytesRead); + m_totalBytesRead += bytesRead; + m_client->OnTransferSizeUpdated(m_totalBytesRead); + + if (m_device->atEnd() || (m_maxBytesToRead > 0 && m_totalBytesRead >= m_maxBytesToRead)) { + OnTransferComplete(MOJO_RESULT_OK); + return true; // Done with reading + } + + if (readResult == 0) + return false; // Wait for readyRead + if (readResult < 0) + break; + } + + CompleteWithFailure(m_error ? net::Error(m_error) : net::ERR_FAILED); + return true; // Done with reading + } + bool ParseRange(const net::HttpRequestHeaders &headers) + { + std::string range_header; + if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) { + std::vector<net::HttpByteRange> ranges; + if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) { + // Chromium doesn't support multirange requests. + if (ranges.size() == 1) { + m_byteRange = ranges[0]; + return true; + } } - } while (m_device->bytesAvailable()); - m_client->OnTransferSizeUpdated(m_totalBytesRead); - if (m_device->atEnd()) - OnTransferComplete(MOJO_RESULT_OK); + } + return false; } - base::TaskRunner *taskRunner() override + base::SequencedTaskRunner *taskRunner() override { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); return m_taskRunner.get(); } - scoped_refptr<base::TaskRunner> m_taskRunner; + scoped_refptr<base::SequencedTaskRunner> m_taskRunner; scoped_refptr<URLRequestCustomJobProxy> m_proxy; mojo::Binding<network::mojom::URLLoader> m_binding; network::mojom::URLLoaderClientPtr m_client; mojo::DataPipe m_pipe; + std::unique_ptr<mojo::SimpleWatcher> m_watcher; + net::HttpByteRange m_byteRange; + int64_t m_totalSize = 0; + int64_t m_maxBytesToRead = -1; network::ResourceRequest m_request; - network::ResourceResponseHead m_head; + network::mojom::URLResponseHeadPtr m_head; + qint64 m_headerBytesRead = 0; qint64 m_totalBytesRead = 0; bool m_corsEnabled; + base::WeakPtrFactory<CustomURLLoader> m_weakPtrFactory{this}; + DISALLOW_COPY_AND_ASSIGN(CustomURLLoader); }; class CustomURLLoaderFactory : public network::mojom::URLLoaderFactory { public: - CustomURLLoaderFactory(ProfileAdapter *profileAdapter) + CustomURLLoaderFactory(ProfileAdapter *profileAdapter, mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) : m_taskRunner(base::CreateSequencedTaskRunner({ content::BrowserThread::IO })) , m_profileAdapter(profileAdapter) { + m_receivers.set_disconnect_handler(base::BindRepeating( + &CustomURLLoaderFactory::OnDisconnect, base::Unretained(this))); + m_receivers.Add(this, std::move(receiver)); } ~CustomURLLoaderFactory() override = default; // network::mojom::URLLoaderFactory: - void CreateLoaderAndStart(network::mojom::URLLoaderRequest loader, + void CreateLoaderAndStart(mojo::PendingReceiver<network::mojom::URLLoader> loader, int32_t routing_id, int32_t request_id, uint32_t options, const network::ResourceRequest &request, - network::mojom::URLLoaderClientPtr client, + mojo::PendingRemote<network::mojom::URLLoaderClient> client, const net::MutableNetworkTrafficAnnotationTag &traffic_annotation) override { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -374,27 +486,40 @@ public: m_taskRunner->PostTask(FROM_HERE, base::BindOnce(&CustomURLLoader::CreateAndStart, request, - std::move(loader), client.PassInterface(), + std::move(loader), std::move(client), m_profileAdapter)); } - void Clone(network::mojom::URLLoaderFactoryRequest request) override + void Clone(mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) override + { + m_receivers.Add(this, std::move(receiver)); + } + + void OnDisconnect() + { + if (m_receivers.empty()) + delete this; + } + + static mojo::PendingRemote<network::mojom::URLLoaderFactory> Create(ProfileAdapter *profileAdapter) { - m_bindings.AddBinding(this, std::move(request)); + mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_remote; + new CustomURLLoaderFactory(profileAdapter, pending_remote.InitWithNewPipeAndPassReceiver()); + return pending_remote; } const scoped_refptr<base::SequencedTaskRunner> m_taskRunner; - mojo::BindingSet<network::mojom::URLLoaderFactory> m_bindings; + mojo::ReceiverSet<network::mojom::URLLoaderFactory> m_receivers; QPointer<ProfileAdapter> m_profileAdapter; DISALLOW_COPY_AND_ASSIGN(CustomURLLoaderFactory); }; } // namespace -std::unique_ptr<network::mojom::URLLoaderFactory> CreateCustomURLLoaderFactory(ProfileAdapter *profileAdapter) +mojo::PendingRemote<network::mojom::URLLoaderFactory> CreateCustomURLLoaderFactory(ProfileAdapter *profileAdapter) { - return std::make_unique<CustomURLLoaderFactory>(profileAdapter); + return CustomURLLoaderFactory::Create(profileAdapter); } } // namespace QtWebEngineCore diff --git a/src/core/net/custom_url_loader_factory.h b/src/core/net/custom_url_loader_factory.h index 58adf4b79..a9eecbd1c 100644 --- a/src/core/net/custom_url_loader_factory.h +++ b/src/core/net/custom_url_loader_factory.h @@ -51,7 +51,7 @@ #ifndef CUSTOM_URL_LOADER_FACTORY_H_ #define CUSTOM_URL_LOADER_FACTORY_H_ -#include <memory> +#include "mojo/public/cpp/bindings/pending_remote.h" namespace network { namespace mojom { @@ -62,7 +62,7 @@ class URLLoaderFactory; namespace QtWebEngineCore { class ProfileAdapter; -std::unique_ptr<network::mojom::URLLoaderFactory> CreateCustomURLLoaderFactory(ProfileAdapter *profileAdapter); +mojo::PendingRemote<network::mojom::URLLoaderFactory> CreateCustomURLLoaderFactory(ProfileAdapter *profileAdapter); } // namespace QtWebEngineCore diff --git a/src/core/net/network_delegate_qt.cpp b/src/core/net/network_delegate_qt.cpp deleted file mode 100644 index 684558abb..000000000 --- a/src/core/net/network_delegate_qt.cpp +++ /dev/null @@ -1,304 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "network_delegate_qt.h" - -#include "base/task/post_task.h" -#include "content/browser/web_contents/web_contents_impl.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/render_view_host.h" -#include "content/public/browser/resource_request_info.h" -#include "net/base/load_flags.h" -#include "net/url_request/url_request.h" -#include "ui/base/page_transition_types.h" - -#include "profile_adapter.h" -#include "cookie_monster_delegate_qt.h" -#include "profile_io_data_qt.h" -#include "qwebengineurlrequestinfo.h" -#include "qwebengineurlrequestinfo_p.h" -#include "qwebengineurlrequestinterceptor.h" -#include "type_conversion.h" -#include "web_contents_adapter_client.h" -#include "web_contents_view_qt.h" -#include "url_request_notification.h" - -namespace QtWebEngineCore { - -WebContentsAdapterClient::NavigationType pageTransitionToNavigationType(ui::PageTransition transition) -{ - if (ui::PageTransitionIsRedirect(transition)) - return WebContentsAdapterClient::RedirectNavigation; - - int32_t qualifier = ui::PageTransitionGetQualifier(transition); - - if (qualifier & ui::PAGE_TRANSITION_FORWARD_BACK) - return WebContentsAdapterClient::BackForwardNavigation; - - ui::PageTransition strippedTransition = ui::PageTransitionStripQualifier(transition); - - switch (strippedTransition) { - case ui::PAGE_TRANSITION_LINK: - return WebContentsAdapterClient::LinkNavigation; - case ui::PAGE_TRANSITION_TYPED: - return WebContentsAdapterClient::TypedNavigation; - case ui::PAGE_TRANSITION_FORM_SUBMIT: - return WebContentsAdapterClient::FormSubmittedNavigation; - case ui::PAGE_TRANSITION_RELOAD: - return WebContentsAdapterClient::ReloadNavigation; - default: - return WebContentsAdapterClient::OtherNavigation; - } -} - -static QWebEngineUrlRequestInfo::ResourceType toQt(content::ResourceType resourceType) -{ - if (resourceType >= content::ResourceType::kMainFrame && resourceType <= content::ResourceType::kMaxValue) - return static_cast<QWebEngineUrlRequestInfo::ResourceType>(resourceType); - return QWebEngineUrlRequestInfo::ResourceTypeUnknown; -} - -static QWebEngineUrlRequestInfo::NavigationType toQt(WebContentsAdapterClient::NavigationType navigationType) -{ - return static_cast<QWebEngineUrlRequestInfo::NavigationType>(navigationType); -} - -NetworkDelegateQt::NetworkDelegateQt(ProfileIODataQt *data) - : m_profileIOData(data) -{ -} - -int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, net::CompletionOnceCallback callback, GURL *newUrl) -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_ASSERT(m_profileIOData); - content::ResourceRequestInfo *resourceInfo = content::ResourceRequestInfo::ForRequest(request); - - content::ResourceType resourceType = content::ResourceType::kMaxValue; - WebContentsAdapterClient::NavigationType navigationType = WebContentsAdapterClient::OtherNavigation; - - if (resourceInfo) { - resourceType = resourceInfo->GetResourceType(); - navigationType = pageTransitionToNavigationType(resourceInfo->GetPageTransition()); - } - - const QUrl qUrl = toQt(request->url()); - - QUrl firstPartyUrl = QUrl(); - if (resourceType == content::ResourceType::kSubFrame) - firstPartyUrl = toQt(request->first_party_url()); - else - firstPartyUrl = toQt(request->site_for_cookies()); - - const QUrl initiator = request->initiator().has_value() ? toQt(request->initiator()->GetURL()) : QUrl(); - - QWebEngineUrlRequestInfoPrivate *infoPrivate = new QWebEngineUrlRequestInfoPrivate(toQt(resourceType), - toQt(navigationType), - qUrl, - firstPartyUrl, - initiator, - QByteArray::fromStdString(request->method())); - QWebEngineUrlRequestInfo requestInfo(infoPrivate); - - // Deprecated =begin - // quick peek if deprecated - - if (m_profileIOData->isInterceptorDeprecated()) { - QWebEngineUrlRequestInterceptor *profileInterceptor = m_profileIOData->acquireInterceptor(); - if (profileInterceptor && m_profileIOData->isInterceptorDeprecated()) { - profileInterceptor->interceptRequest(requestInfo); - m_profileIOData->releaseInterceptor(); - if (requestInfo.changed()) { - int result = infoPrivate->shouldBlockRequest ? net::ERR_BLOCKED_BY_CLIENT : net::OK; - - if (qUrl != infoPrivate->url) - *newUrl = toGurl(infoPrivate->url); - - if (!infoPrivate->extraHeaders.isEmpty()) { - auto end = infoPrivate->extraHeaders.constEnd(); - for (auto header = infoPrivate->extraHeaders.constBegin(); header != end; ++header) { - std::string h = header.key().toStdString(); - if (base::LowerCaseEqualsASCII(h, "referer")) { - request->SetReferrer(header.value().toStdString()); - } else { - request->SetExtraRequestHeaderByName(h, header.value().toStdString(), /* overwrite */ true); - } - } - } - - if (result != net::OK) - return result; - - requestInfo.resetChanged(); - } - } else { - m_profileIOData->releaseInterceptor(); - } - } - // Deprecated =cut - - if (!resourceInfo) - return net::OK; - - // try to bail out - if (!m_profileIOData->hasPageInterceptors() && (!m_profileIOData->requestInterceptor() || m_profileIOData->isInterceptorDeprecated())) - return net::OK; - - auto webContentsGetter = resourceInfo->GetWebContentsGetterForRequest(); - new URLRequestNotification( - request, - resourceInfo->IsMainFrame(), - newUrl, - std::move(requestInfo), - webContentsGetter, - std::move(callback), - m_profileIOData->profileAdapter() - ); - - // We'll run the callback after we notified the UI thread. - return net::ERR_IO_PENDING; -} - -void NetworkDelegateQt::OnURLRequestDestroyed(net::URLRequest *) {} - -void NetworkDelegateQt::OnCompleted(net::URLRequest * /*request*/, bool /*started*/, int /*net_error*/) {} - -bool NetworkDelegateQt::OnCanSetCookie(const net::URLRequest &request, const net::CanonicalCookie & /*cookie*/, - net::CookieOptions *, bool allowedFromCaller) -{ - if (!allowedFromCaller) - return false; - return canSetCookies(request.site_for_cookies(), request.url(), std::string()); -} - -bool NetworkDelegateQt::OnCanGetCookies(const net::URLRequest &request, const net::CookieList &, bool allowedFromCaller) -{ - if (!allowedFromCaller) - return false; - return canGetCookies(request.site_for_cookies(), request.url()); -} - -bool NetworkDelegateQt::OnForcePrivacyMode(const GURL &url, const GURL &site_for_cookies) const -{ - return false; - // FIXME: This is what the NetworkContext implementation does (changes tst_QWebEngineCookieStore tests since 72) - // return !canGetCookies(site_for_cookies, url); -} - -bool NetworkDelegateQt::canSetCookies(const GURL &first_party, const GURL &url, const std::string &cookie_line) const -{ - Q_ASSERT(m_profileIOData); - return m_profileIOData->canSetCookie(toQt(first_party), QByteArray::fromStdString(cookie_line), toQt(url)); -} - -bool NetworkDelegateQt::canGetCookies(const GURL &first_party, const GURL &url) const -{ - Q_ASSERT(m_profileIOData); - return m_profileIOData->canGetCookies(toQt(first_party), toQt(url)); -} - -int NetworkDelegateQt::OnBeforeStartTransaction(net::URLRequest *, net::CompletionOnceCallback, net::HttpRequestHeaders *) -{ - return net::OK; -} - -void NetworkDelegateQt::OnBeforeSendHeaders(net::URLRequest *request, const net::ProxyInfo &proxy_info, - const net::ProxyRetryInfoMap &proxy_retry_info, - net::HttpRequestHeaders *headers) -{} - -void NetworkDelegateQt::OnStartTransaction(net::URLRequest *request, const net::HttpRequestHeaders &headers) {} - -int NetworkDelegateQt::OnHeadersReceived(net::URLRequest *, net::CompletionOnceCallback, const net::HttpResponseHeaders *, - scoped_refptr<net::HttpResponseHeaders> *, GURL *) -{ - return net::OK; -} - -void NetworkDelegateQt::OnBeforeRedirect(net::URLRequest *, const GURL &) {} - -void NetworkDelegateQt::OnResponseStarted(net::URLRequest *, int) {} - -void NetworkDelegateQt::OnNetworkBytesReceived(net::URLRequest *, int64_t) {} - -void NetworkDelegateQt::OnNetworkBytesSent(net::URLRequest *, int64_t) {} - -void NetworkDelegateQt::OnPACScriptError(int, const base::string16 &) {} - -net::NetworkDelegate::AuthRequiredResponse NetworkDelegateQt::OnAuthRequired(net::URLRequest *, - const net::AuthChallengeInfo &, - AuthCallback, net::AuthCredentials *) -{ - return AUTH_REQUIRED_RESPONSE_NO_ACTION; -} - -bool NetworkDelegateQt::OnCanAccessFile(const net::URLRequest &, const base::FilePath &, const base::FilePath &) const -{ - return true; -} - -bool NetworkDelegateQt::OnCancelURLRequestWithPolicyViolatingReferrerHeader(const net::URLRequest &, const GURL &, - const GURL &) const -{ - return false; -} - -bool NetworkDelegateQt::OnCanQueueReportingReport(const url::Origin &origin) const -{ - return false; -} - -void NetworkDelegateQt::OnCanSendReportingReports(std::set<url::Origin> origins, - base::OnceCallback<void(std::set<url::Origin>)> result_callback) const -{ - std::move(result_callback).Run(std::set<url::Origin>()); -} - -bool NetworkDelegateQt::OnCanSetReportingClient(const url::Origin &origin, const GURL &endpoint) const -{ - return false; -} - -bool NetworkDelegateQt::OnCanUseReportingClient(const url::Origin &origin, const GURL &endpoint) const -{ - return false; -} - -} // namespace QtWebEngineCore diff --git a/src/core/net/network_delegate_qt.h b/src/core/net/network_delegate_qt.h deleted file mode 100644 index f294c6c7c..000000000 --- a/src/core/net/network_delegate_qt.h +++ /dev/null @@ -1,102 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef NETWORK_DELEGATE_QT_H -#define NETWORK_DELEGATE_QT_H - -#include "net/base/network_delegate.h" -#include "net/base/net_errors.h" - -#include <QUrl> -#include <QSet> - -namespace content { -class WebContents; -} - -namespace QtWebEngineCore { - -class ProfileIODataQt; - -class NetworkDelegateQt : public net::NetworkDelegate -{ - ProfileIODataQt *m_profileIOData; - -public: - NetworkDelegateQt(ProfileIODataQt *data); - - // net::NetworkDelegate implementation - int OnBeforeURLRequest(net::URLRequest *request, net::CompletionOnceCallback callback, GURL *new_url) override; - void OnURLRequestDestroyed(net::URLRequest *request) override; - bool OnCanSetCookie(const net::URLRequest &request, const net::CanonicalCookie &cookie, net::CookieOptions *options, - bool) override; - int OnBeforeStartTransaction(net::URLRequest *request, const net::CompletionOnceCallback callback, - net::HttpRequestHeaders *headers) override; - void OnBeforeSendHeaders(net::URLRequest *request, const net::ProxyInfo &proxy_info, - const net::ProxyRetryInfoMap &proxy_retry_info, net::HttpRequestHeaders *headers) override; - void OnStartTransaction(net::URLRequest *request, const net::HttpRequestHeaders &headers) override; - int OnHeadersReceived(net::URLRequest *, net::CompletionOnceCallback, const net::HttpResponseHeaders *, - scoped_refptr<net::HttpResponseHeaders> *, GURL *) override; - void OnBeforeRedirect(net::URLRequest *, const GURL &) override; - void OnResponseStarted(net::URLRequest *, int) override; - void OnNetworkBytesReceived(net::URLRequest *, int64_t) override; - void OnNetworkBytesSent(net::URLRequest *, int64_t) override; - void OnCompleted(net::URLRequest *request, bool started, int net_error) override; - void OnPACScriptError(int, const base::string16 &) override; - net::NetworkDelegate::AuthRequiredResponse OnAuthRequired(net::URLRequest *, const net::AuthChallengeInfo &, - AuthCallback, net::AuthCredentials *) override; - bool OnCanGetCookies(const net::URLRequest &, const net::CookieList &, bool) override; - bool OnCanAccessFile(const net::URLRequest &, const base::FilePath &, const base::FilePath &) const override; - bool OnForcePrivacyMode(const GURL &, const GURL &) const override; - bool OnCancelURLRequestWithPolicyViolatingReferrerHeader(const net::URLRequest &, const GURL &, - const GURL &) const override; - - bool OnCanQueueReportingReport(const url::Origin &origin) const override; - void OnCanSendReportingReports(std::set<url::Origin> origins, - base::OnceCallback<void(std::set<url::Origin>)> result_callback) const override; - bool OnCanSetReportingClient(const url::Origin &origin, const GURL &endpoint) const override; - bool OnCanUseReportingClient(const url::Origin &origin, const GURL &endpoint) const override; - - bool canSetCookies(const GURL &first_party, const GURL &url, const std::string &cookie_line) const; - bool canGetCookies(const GURL &first_party, const GURL &url) const; -}; - -} // namespace QtWebEngineCore - -#endif // NETWORK_DELEGATE_QT_H diff --git a/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp b/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp new file mode 100644 index 000000000..d868e4f54 --- /dev/null +++ b/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp @@ -0,0 +1,180 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "plugin_response_interceptor_url_loader_throttle.h" + +#include "base/bind.h" +#include "base/guid.h" +#include "base/task/post_task.h" +#include "chrome/browser/extensions/api/streams_private/streams_private_api.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/download_manager.h" +#include "content/public/browser/download_request_utils.h" +#include "content/public/browser/download_utils.h" +#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_attach_helper.h" +#include "extensions/common/constants.h" +#include "extensions/common/extension.h" +#include "extensions/common/manifest_handlers/mime_types_handler.h" +#include "third_party/blink/public/mojom/loader/transferrable_url_loader.mojom.h" + +#include "extensions/extension_system_qt.h" +#include "web_contents_delegate_qt.h" + +#include <string> + +namespace QtWebEngineCore { + +PluginResponseInterceptorURLLoaderThrottle::PluginResponseInterceptorURLLoaderThrottle( + content::BrowserContext *browser_context, int resource_type, int frame_tree_node_id) + : m_browser_context(browser_context), m_resource_type(resource_type), m_frame_tree_node_id(frame_tree_node_id) +{} + +void PluginResponseInterceptorURLLoaderThrottle::WillProcessResponse(const GURL &response_url, + network::mojom::URLResponseHead *response_head, + bool *defer) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (content::download_utils::MustDownload(response_url, response_head->headers.get(), response_head->mime_type)) + return; + + content::WebContents *web_contents = content::WebContents::FromFrameTreeNodeId(m_frame_tree_node_id); + if (!web_contents) + return; + + std::string extension_id; + if (response_head->mime_type == "application/pdf") + extension_id = extension_misc::kPdfExtensionId; + if (extension_id.empty()) + return; + + WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt *>(web_contents->GetDelegate()); + if (!contentsDelegate) + return; + + WebEngineSettings *settings = contentsDelegate->webEngineSettings(); + if (!settings->testAttribute(WebEngineSettings::PdfViewerEnabled) + || !settings->testAttribute(WebEngineSettings::PluginsEnabled)) { + // PluginServiceFilterQt will inform the URLLoader about the disabled state of plugins + // and we can expect the download to be triggered automatically. It's unnecessary to + // go further and start the guest view embedding process. + return; + } + + // Chrome's PDF Extension does not work properly in the face of a restrictive + // Content-Security-Policy, and does not currently respect the policy anyway. + // Ignore CSP served on a PDF response. https://crbug.com/271452 + if (extension_id == extension_misc::kPdfExtensionId && response_head->headers) + response_head->headers->RemoveHeader("Content-Security-Policy"); + + MimeTypesHandler::ReportUsedHandler(extension_id); + + std::string view_id = base::GenerateGUID(); + // The string passed down to the original client with the response body. + std::string payload = view_id; + + mojo::PendingRemote<network::mojom::URLLoader> dummy_new_loader; + ignore_result(dummy_new_loader.InitWithNewPipeAndPassReceiver()); + mojo::Remote<network::mojom::URLLoaderClient> new_client; + mojo::PendingReceiver<network::mojom::URLLoaderClient> new_client_receiver = + new_client.BindNewPipeAndPassReceiver(); + + + uint32_t data_pipe_size = 64U; + // Provide the MimeHandlerView code a chance to override the payload. This is + // the case where the resource is handled by frame-based MimeHandlerView. + *defer = extensions::MimeHandlerViewAttachHelper::OverrideBodyForInterceptedResponse( + m_frame_tree_node_id, response_url, response_head->mime_type, view_id, + &payload, &data_pipe_size, + base::BindOnce( + &PluginResponseInterceptorURLLoaderThrottle::ResumeLoad, + weak_factory_.GetWeakPtr())); + + mojo::DataPipe data_pipe(data_pipe_size); + uint32_t len = static_cast<uint32_t>(payload.size()); + CHECK_EQ(MOJO_RESULT_OK, + data_pipe.producer_handle->WriteData( + payload.c_str(), &len, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE)); + + + new_client->OnStartLoadingResponseBody(std::move(data_pipe.consumer_handle)); + + network::URLLoaderCompletionStatus status(net::OK); + status.decoded_body_length = len; + new_client->OnComplete(status); + + mojo::PendingRemote<network::mojom::URLLoader> original_loader; + mojo::PendingReceiver<network::mojom::URLLoaderClient> original_client; + delegate_->InterceptResponse(std::move(dummy_new_loader), + std::move(new_client_receiver), &original_loader, + &original_client); + + // Make a deep copy of URLResponseHead before passing it cross-thread. + auto deep_copied_response = response_head->Clone(); + if (response_head->headers) { + deep_copied_response->headers = + base::MakeRefCounted<net::HttpResponseHeaders>( + response_head->headers->raw_headers()); + } + + auto transferrable_loader = blink::mojom::TransferrableURLLoader::New(); + transferrable_loader->url = GURL( + extensions::Extension::GetBaseURLFromExtensionId(extension_id).spec() + + base::GenerateGUID()); + transferrable_loader->url_loader = std::move(original_loader); + transferrable_loader->url_loader_client = std::move(original_client); + transferrable_loader->head = std::move(deep_copied_response); + transferrable_loader->head->intercepted_by_plugin = true; + + bool embedded = m_resource_type != + static_cast<int>(blink::mojom::ResourceType::kMainFrame); + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, + base::BindOnce( + &extensions::StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent, + extension_id, view_id, embedded, m_frame_tree_node_id, + -1 /* render_process_id */, -1 /* render_frame_id */, + std::move(transferrable_loader), response_url)); +} + +void PluginResponseInterceptorURLLoaderThrottle::ResumeLoad() { + delegate_->Resume(); +} + +} // namespace QtWebEngineCore diff --git a/src/core/net/url_request_notification.h b/src/core/net/plugin_response_interceptor_url_loader_throttle.h index 673e07bf0..205ab25e6 100644 --- a/src/core/net/url_request_notification.h +++ b/src/core/net/plugin_response_interceptor_url_loader_throttle.h @@ -37,50 +37,44 @@ ** ****************************************************************************/ -#ifndef URL_REQUEST_NOTIFIACTION_H -#define URL_REQUEST_NOTIFIACTION_H +#ifndef PLUGIN_RESPONSE_INTERCEPTOR_URL_LOADER_THROTTLE_H_ +#define PLUGIN_RESPONSE_INTERCEPTOR_URL_LOADER_THROTTLE_H_ -#include "content/public/browser/resource_request_info.h" -#include "net/base/completion_once_callback.h" -#include "qwebengineurlrequestinfo.h" -#include <QPointer> +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "third_party/blink/public/common/loader/url_loader_throttle.h" -class GURL; - -namespace net { -class URLRequest; +namespace content { +class BrowserContext; } namespace QtWebEngineCore { -class ProfileAdapter; -class ProfileIoDataQt; - -// Notifies WebContentsAdapterClient of a new URLRequest. -class URLRequestNotification +class PluginResponseInterceptorURLLoaderThrottle : public blink::URLLoaderThrottle { public: - URLRequestNotification(net::URLRequest *request, - bool isMainFrameRequest, - GURL *newUrl, - QWebEngineUrlRequestInfo &&requestInfo, - content::ResourceRequestInfo::WebContentsGetter webContentsGetter, - net::CompletionOnceCallback callback, - QPointer<ProfileAdapter> adapter); - ~URLRequestNotification() = default; - void cancel(); - void notify(); - void complete(int error); + PluginResponseInterceptorURLLoaderThrottle(content::BrowserContext *browser_context, + int resource_type, int frame_tree_node_id); + ~PluginResponseInterceptorURLLoaderThrottle() override = default; private: - net::URLRequest *m_request; //used only by io thread - bool m_isMainFrameRequest; - GURL *m_newUrl; - const QUrl m_originalUrl; - QWebEngineUrlRequestInfo m_requestInfo; - content::ResourceRequestInfo::WebContentsGetter m_webContentsGetter; - net::CompletionOnceCallback m_callback; - QPointer<ProfileAdapter> m_profileAdapter; + // content::URLLoaderThrottle overrides; + void WillProcessResponse(const GURL &response_url, network::mojom::URLResponseHead *response_head, bool *defer) override; + + // Resumes loading for an intercepted response. This would give the extension + // layer chance to initialize its browser side state. + void ResumeLoad(); + + content::BrowserContext *m_browser_context = nullptr; + const int m_resource_type; + const int m_frame_tree_node_id; + + base::WeakPtrFactory<PluginResponseInterceptorURLLoaderThrottle> + weak_factory_{this}; + + DISALLOW_COPY_AND_ASSIGN(PluginResponseInterceptorURLLoaderThrottle); }; -} -#endif + +} // namespace QtWebEngineCore + +#endif // PLUGIN_RESPONSE_INTERCEPTOR_URL_LOADER_THROTTLE_H_ diff --git a/src/core/net/proxy_config_monitor.cpp b/src/core/net/proxy_config_monitor.cpp index 818b6cb7f..a0aaf0c05 100644 --- a/src/core/net/proxy_config_monitor.cpp +++ b/src/core/net/proxy_config_monitor.cpp @@ -67,7 +67,7 @@ ProxyConfigMonitor::ProxyConfigMonitor(PrefService *prefs) proxy_config_service_.reset( new ProxyConfigServiceQt( - prefs, base::CreateSingleThreadTaskRunnerWithTraits({ BrowserThread::UI }))); + prefs, base::CreateSingleThreadTaskRunner({ BrowserThread::UI }))); proxy_config_service_->AddObserver(this); } @@ -82,12 +82,13 @@ ProxyConfigMonitor::~ProxyConfigMonitor() void ProxyConfigMonitor::AddToNetworkContextParams( network::mojom::NetworkContextParams *network_context_params) { - network::mojom::ProxyConfigClientPtr proxy_config_client; - network_context_params->proxy_config_client_request = mojo::MakeRequest(&proxy_config_client); - proxy_config_client_set_.AddPtr(std::move(proxy_config_client)); + mojo::PendingRemote<network::mojom::ProxyConfigClient> proxy_config_client; + network_context_params->proxy_config_client_receiver = + proxy_config_client.InitWithNewPipeAndPassReceiver(); + proxy_config_client_set_.Add(std::move(proxy_config_client)); - poller_binding_set_.AddBinding( - this, mojo::MakeRequest(&network_context_params->proxy_config_poller_client)); + poller_receiver_set_.Add(this, + network_context_params->proxy_config_poller_client.InitWithNewPipeAndPassReceiver()); net::ProxyConfigWithAnnotation proxy_config; net::ProxyConfigService::ConfigAvailability availability = @@ -102,21 +103,19 @@ void ProxyConfigMonitor::OnProxyConfigChanged( { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || !BrowserThread::IsThreadInitialized(BrowserThread::UI)); - proxy_config_client_set_.ForAllPtrs( - [config, availability](network::mojom::ProxyConfigClient *proxy_config_client) { - switch (availability) { - case net::ProxyConfigService::CONFIG_VALID: - proxy_config_client->OnProxyConfigUpdated(config); - break; - case net::ProxyConfigService::CONFIG_UNSET: - proxy_config_client->OnProxyConfigUpdated( - net::ProxyConfigWithAnnotation::CreateDirect()); - break; - case net::ProxyConfigService::CONFIG_PENDING: - NOTREACHED(); - break; - } - }); + for (const auto &proxy_config_client : proxy_config_client_set_) { + switch (availability) { + case net::ProxyConfigService::CONFIG_VALID: + proxy_config_client->OnProxyConfigUpdated(config); + break; + case net::ProxyConfigService::CONFIG_UNSET: + proxy_config_client->OnProxyConfigUpdated(net::ProxyConfigWithAnnotation::CreateDirect()); + break; + case net::ProxyConfigService::CONFIG_PENDING: + NOTREACHED(); + break; + } + } } void ProxyConfigMonitor::OnLazyProxyConfigPoll() diff --git a/src/core/net/proxy_config_monitor.h b/src/core/net/proxy_config_monitor.h index 23f073a84..fda6a6fb9 100644 --- a/src/core/net/proxy_config_monitor.h +++ b/src/core/net/proxy_config_monitor.h @@ -51,8 +51,8 @@ #include "base/macros.h" #include "build/buildflag.h" #include "extensions/buildflags/buildflags.h" -#include "mojo/public/cpp/bindings/binding_set.h" -#include "mojo/public/cpp/bindings/interface_ptr_set.h" +#include "mojo/public/cpp/bindings/receiver_set.h" +#include "mojo/public/cpp/bindings/remote_set.h" #include "net/proxy_resolution/proxy_config_service.h" #include "services/network/public/mojom/network_context.mojom-forward.h" #include "services/network/public/mojom/network_service.mojom-forward.h" @@ -94,9 +94,8 @@ private: std::unique_ptr<ProxyConfigServiceQt> proxy_config_service_; - mojo::BindingSet<network::mojom::ProxyConfigPollerClient> poller_binding_set_; - - mojo::InterfacePtrSet<network::mojom::ProxyConfigClient> proxy_config_client_set_; + mojo::ReceiverSet<network::mojom::ProxyConfigPollerClient> poller_receiver_set_; + mojo::RemoteSet<network::mojom::ProxyConfigClient> proxy_config_client_set_; DISALLOW_COPY_AND_ASSIGN(ProxyConfigMonitor); }; diff --git a/src/core/net/proxy_config_service_qt.cpp b/src/core/net/proxy_config_service_qt.cpp index 59884961d..bc934c960 100644 --- a/src/core/net/proxy_config_service_qt.cpp +++ b/src/core/net/proxy_config_service_qt.cpp @@ -48,7 +48,7 @@ #include "base/bind.h" #include "components/proxy_config/pref_proxy_config_tracker_impl.h" #include "content/public/browser/browser_thread.h" -#include "net/proxy_resolution/proxy_resolution_service.h" +#include "net/proxy_resolution/configured_proxy_resolution_service.h" using content::BrowserThread; @@ -72,7 +72,7 @@ net::ProxyServer ProxyConfigServiceQt::fromQNetworkProxy(const QNetworkProxy &qt ProxyConfigServiceQt::ProxyConfigServiceQt(PrefService *prefService, const scoped_refptr<base::SingleThreadTaskRunner> &taskRunner) - : m_baseService(net::ProxyResolutionService::CreateSystemProxyConfigService(taskRunner)) + : m_baseService(net::ConfiguredProxyResolutionService::CreateSystemProxyConfigService(taskRunner)) , m_usesSystemConfiguration(false) , m_registeredObserver(false) , m_prefState(prefService diff --git a/src/core/net/proxying_restricted_cookie_manager_qt.cpp b/src/core/net/proxying_restricted_cookie_manager_qt.cpp index b6abeb567..f86c0e997 100644 --- a/src/core/net/proxying_restricted_cookie_manager_qt.cpp +++ b/src/core/net/proxying_restricted_cookie_manager_qt.cpp @@ -54,76 +54,52 @@ #include "base/task/post_task.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" -#include "mojo/public/cpp/bindings/strong_binding.h" +#include "mojo/public/cpp/bindings/self_owned_receiver.h" namespace QtWebEngineCore { -class ProxyingRestrictedCookieManagerListenerQt : public network::mojom::CookieChangeListener { -public: - ProxyingRestrictedCookieManagerListenerQt(const GURL &url, - const GURL &site_for_cookies, - base::WeakPtr<ProxyingRestrictedCookieManagerQt> restricted_cookie_manager, - network::mojom::CookieChangeListenerPtr client_listener) - : url_(url) - , site_for_cookies_(site_for_cookies) - , restricted_cookie_manager_(restricted_cookie_manager) - , client_listener_(std::move(client_listener)) - {} - - void OnCookieChange(const net::CanonicalCookie &cookie, network::mojom::CookieChangeCause cause) override - { - if (restricted_cookie_manager_ && restricted_cookie_manager_->allowCookies(url_, site_for_cookies_)) - client_listener_->OnCookieChange(cookie, cause); - } - -private: - const GURL url_; - const GURL site_for_cookies_; - base::WeakPtr<ProxyingRestrictedCookieManagerQt> restricted_cookie_manager_; - network::mojom::CookieChangeListenerPtr client_listener_; -}; - // static void ProxyingRestrictedCookieManagerQt::CreateAndBind(ProfileIODataQt *profileIoData, - network::mojom::RestrictedCookieManagerPtrInfo underlying_rcm, + mojo::PendingRemote<network::mojom::RestrictedCookieManager> underlying_rcm, bool is_service_worker, int process_id, int frame_id, - network::mojom::RestrictedCookieManagerRequest request) + mojo::PendingReceiver<network::mojom::RestrictedCookieManager> receiver) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&ProxyingRestrictedCookieManagerQt::CreateAndBindOnIoThread, - profileIoData, - std::move(underlying_rcm), - is_service_worker, process_id, frame_id, - std::move(request))); + base::PostTask(FROM_HERE, {content::BrowserThread::IO}, + base::BindOnce(&ProxyingRestrictedCookieManagerQt::CreateAndBindOnIoThread, + profileIoData, + std::move(underlying_rcm), + is_service_worker, process_id, frame_id, + std::move(receiver))); } // static void ProxyingRestrictedCookieManagerQt::CreateAndBindOnIoThread(ProfileIODataQt *profileIoData, - network::mojom::RestrictedCookieManagerPtrInfo underlying_rcm, + mojo::PendingRemote<network::mojom::RestrictedCookieManager> underlying_rcm, bool is_service_worker, int process_id, int frame_id, - network::mojom::RestrictedCookieManagerRequest request) + mojo::PendingReceiver<network::mojom::RestrictedCookieManager> receiver) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); auto wrapper = base::WrapUnique(new ProxyingRestrictedCookieManagerQt( profileIoData->getWeakPtrOnIOThread(), - network::mojom::RestrictedCookieManagerPtr(std::move(underlying_rcm)), + std::move(underlying_rcm), is_service_worker, process_id, frame_id)); - mojo::MakeStrongBinding(std::move(wrapper), std::move(request)); + mojo::MakeSelfOwnedReceiver(std::move(wrapper), std::move(receiver)); } -ProxyingRestrictedCookieManagerQt::ProxyingRestrictedCookieManagerQt(base::WeakPtr<ProfileIODataQt> profileIoData, - network::mojom::RestrictedCookieManagerPtr underlyingRestrictedCookieManager, - bool is_service_worker, - int32_t process_id, - int32_t frame_id) +ProxyingRestrictedCookieManagerQt::ProxyingRestrictedCookieManagerQt( + base::WeakPtr<ProfileIODataQt> profileIoData, + mojo::PendingRemote<network::mojom::RestrictedCookieManager> underlyingRestrictedCookieManager, + bool is_service_worker, + int32_t process_id, + int32_t frame_id) : m_profileIoData(std::move(profileIoData)) , underlying_restricted_cookie_manager_(std::move(underlyingRestrictedCookieManager)) , is_service_worker_(is_service_worker) @@ -140,92 +116,88 @@ ProxyingRestrictedCookieManagerQt::~ProxyingRestrictedCookieManagerQt() } void ProxyingRestrictedCookieManagerQt::GetAllForUrl(const GURL &url, - const GURL &site_for_cookies, + const net::SiteForCookies &site_for_cookies, + const url::Origin &top_frame_origin, network::mojom::CookieManagerGetOptionsPtr options, GetAllForUrlCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (allowCookies(url, site_for_cookies)) { - underlying_restricted_cookie_manager_->GetAllForUrl(url, site_for_cookies, std::move(options), std::move(callback)); + underlying_restricted_cookie_manager_->GetAllForUrl(url, site_for_cookies, top_frame_origin, std::move(options), std::move(callback)); } else { - std::move(callback).Run(std::vector<net::CanonicalCookie>()); + std::move(callback).Run(std::vector<net::CookieWithAccessResult>()); } } void ProxyingRestrictedCookieManagerQt::SetCanonicalCookie(const net::CanonicalCookie &cookie, const GURL &url, - const GURL &site_for_cookies, + const net::SiteForCookies &site_for_cookies, + const url::Origin &top_frame_origin, SetCanonicalCookieCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (allowCookies(url, site_for_cookies)) { - underlying_restricted_cookie_manager_->SetCanonicalCookie(cookie, url, site_for_cookies, std::move(callback)); + underlying_restricted_cookie_manager_->SetCanonicalCookie(cookie, url, site_for_cookies, top_frame_origin, std::move(callback)); } else { std::move(callback).Run(false); } } void ProxyingRestrictedCookieManagerQt::AddChangeListener(const GURL &url, - const GURL &site_for_cookies, - network::mojom::CookieChangeListenerPtr listener, + const net::SiteForCookies &site_for_cookies, + const url::Origin &top_frame_origin, + mojo::PendingRemote<network::mojom::CookieChangeListener> listener, AddChangeListenerCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - network::mojom::CookieChangeListenerPtr proxy_listener_ptr; - auto proxy_listener = - std::make_unique<ProxyingRestrictedCookieManagerListenerQt>( - url, site_for_cookies, weak_factory_.GetWeakPtr(), - std::move(listener)); - - mojo::MakeStrongBinding(std::move(proxy_listener), - mojo::MakeRequest(&proxy_listener_ptr)); - - underlying_restricted_cookie_manager_->AddChangeListener(url, site_for_cookies, std::move(proxy_listener_ptr), std::move(callback)); + underlying_restricted_cookie_manager_->AddChangeListener(url, site_for_cookies, top_frame_origin, std::move(listener), std::move(callback)); } void ProxyingRestrictedCookieManagerQt::SetCookieFromString(const GURL &url, - const GURL &site_for_cookies, + const net::SiteForCookies &site_for_cookies, + const url::Origin &top_frame_origin, const std::string &cookie, SetCookieFromStringCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (allowCookies(url, site_for_cookies)) { - underlying_restricted_cookie_manager_->SetCookieFromString(url, site_for_cookies, cookie, std::move(callback)); + underlying_restricted_cookie_manager_->SetCookieFromString(url, site_for_cookies, top_frame_origin, cookie, std::move(callback)); } else { std::move(callback).Run(); } } void ProxyingRestrictedCookieManagerQt::GetCookiesString(const GURL &url, - const GURL &site_for_cookies, + const net::SiteForCookies &site_for_cookies, + const url::Origin &top_frame_origin, GetCookiesStringCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (allowCookies(url, site_for_cookies)) { - underlying_restricted_cookie_manager_->GetCookiesString(url, site_for_cookies, std::move(callback)); + underlying_restricted_cookie_manager_->GetCookiesString(url, site_for_cookies, top_frame_origin, std::move(callback)); } else { std::move(callback).Run(""); } } void ProxyingRestrictedCookieManagerQt::CookiesEnabledFor(const GURL &url, - const GURL &site_for_cookies, + const net::SiteForCookies &site_for_cookies, + const url::Origin & /*top_frame_origin*/, CookiesEnabledForCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); std::move(callback).Run(allowCookies(url, site_for_cookies)); } -bool ProxyingRestrictedCookieManagerQt::allowCookies(const GURL &url, const GURL &site_for_cookies) const +bool ProxyingRestrictedCookieManagerQt::allowCookies(const GURL &url, const net::SiteForCookies &site_for_cookies) const { if (!m_profileIoData) return false; - return m_profileIoData->canGetCookies(toQt(site_for_cookies), toQt(url)); + return m_profileIoData->canGetCookies(toQt(site_for_cookies.first_party_url()), toQt(url)); } } // namespace QtWebEngineCore diff --git a/src/core/net/proxying_restricted_cookie_manager_qt.h b/src/core/net/proxying_restricted_cookie_manager_qt.h index 7a9f0e3ab..3d4765b3b 100644 --- a/src/core/net/proxying_restricted_cookie_manager_qt.h +++ b/src/core/net/proxying_restricted_cookie_manager_qt.h @@ -42,6 +42,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "mojo/public/cpp/bindings/remote.h" #include "services/network/public/mojom/restricted_cookie_manager.mojom.h" #include "url/gurl.h" @@ -54,59 +55,64 @@ class ProxyingRestrictedCookieManagerQt : public network::mojom::RestrictedCooki public: // Expects to be called on the UI thread. static void CreateAndBind(ProfileIODataQt *profileIoData, - network::mojom::RestrictedCookieManagerPtrInfo underlying_rcm, + mojo::PendingRemote<network::mojom::RestrictedCookieManager> underlying_rcm, bool is_service_worker, int process_id, int frame_id, - network::mojom::RestrictedCookieManagerRequest request); + mojo::PendingReceiver<network::mojom::RestrictedCookieManager> receiver); ~ProxyingRestrictedCookieManagerQt() override; // network::mojom::RestrictedCookieManager interface: void GetAllForUrl(const GURL &url, - const GURL &site_for_cookies, + const net::SiteForCookies &site_for_cookies, + const url::Origin &top_frame_origin, network::mojom::CookieManagerGetOptionsPtr options, GetAllForUrlCallback callback) override; void SetCanonicalCookie(const net::CanonicalCookie& cookie, const GURL &url, - const GURL &site_for_cookies, + const net::SiteForCookies &site_for_cookies, + const url::Origin &top_frame_origin, SetCanonicalCookieCallback callback) override; void AddChangeListener(const GURL &url, - const GURL &site_for_cookies, - network::mojom::CookieChangeListenerPtr listener, + const net::SiteForCookies &site_for_cookies, + const url::Origin &top_frame_origin, + mojo::PendingRemote<network::mojom::CookieChangeListener> listener, AddChangeListenerCallback callback) override; void SetCookieFromString(const GURL &url, - const GURL &site_for_cookies, + const net::SiteForCookies &site_for_cookies, + const url::Origin &top_frame_origin, const std::string &cookie, SetCookieFromStringCallback callback) override; void GetCookiesString(const GURL &url, - const GURL &site_for_cookies, + const net::SiteForCookies &site_for_cookies, + const url::Origin &top_frame_origin, GetCookiesStringCallback callback) override; - void CookiesEnabledFor(const GURL &url, - const GURL &site_for_cookies, + const net::SiteForCookies &site_for_cookies, + const url::Origin &top_frame_origin, CookiesEnabledForCallback callback) override; // Internal: - bool allowCookies(const GURL &url, const GURL &site_for_cookies) const; + bool allowCookies(const GURL &url, const net::SiteForCookies &site_for_cookies) const; private: ProxyingRestrictedCookieManagerQt(base::WeakPtr<ProfileIODataQt> profileIoData, - network::mojom::RestrictedCookieManagerPtr underlyingRestrictedCookieManager, + mojo::PendingRemote<network::mojom::RestrictedCookieManager> underlying_rcm, bool is_service_worker, int32_t process_id, int32_t frame_id); static void CreateAndBindOnIoThread(ProfileIODataQt *profileIoData, - network::mojom::RestrictedCookieManagerPtrInfo underlying_rcm, + mojo::PendingRemote<network::mojom::RestrictedCookieManager> underlying_rcm, bool is_service_worker, int process_id, int frame_id, - network::mojom::RestrictedCookieManagerRequest request); + mojo::PendingReceiver<network::mojom::RestrictedCookieManager> receiver); base::WeakPtr<ProfileIODataQt> m_profileIoData; - network::mojom::RestrictedCookieManagerPtr underlying_restricted_cookie_manager_; + mojo::Remote<network::mojom::RestrictedCookieManager> underlying_restricted_cookie_manager_; bool is_service_worker_; int process_id_; int frame_id_; diff --git a/src/core/net/proxying_url_loader_factory_qt.cpp b/src/core/net/proxying_url_loader_factory_qt.cpp index 173e19eeb..a016cbc72 100644 --- a/src/core/net/proxying_url_loader_factory_qt.cpp +++ b/src/core/net/proxying_url_loader_factory_qt.cpp @@ -42,30 +42,23 @@ #include <utility> #include "base/bind.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" #include "base/task/post_task.h" -#include "components/safe_browsing/common/safebrowsing_constants.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/global_request_id.h" -#include "content/public/browser/render_process_host.h" -#include "content/public/browser/resource_request_info.h" #include "content/public/browser/web_contents.h" -#include "content/public/common/content_constants.h" -#include "content/public/common/url_utils.h" -#include "net/base/load_flags.h" +#include "content/public/common/content_switches.h" #include "net/http/http_status_code.h" -#include "net/http/http_util.h" +#include "services/network/public/cpp/cors/cors.h" +#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h" +#include "url/url_util.h" #include "api/qwebengineurlrequestinfo_p.h" -#include "net/url_request_custom_job_proxy.h" -#include "net/url_request_notification.h" -#include "profile_io_data_qt.h" #include "type_conversion.h" +#include "web_contents_adapter.h" #include "web_contents_adapter_client.h" #include "web_contents_view_qt.h" + #include <QVariant> // originally based on aw_proxying_url_loader_factory.cc: @@ -73,13 +66,47 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +namespace { + network::mojom::URLResponseHeadPtr createResponse(const network::ResourceRequest &request) { + const bool disable_web_security = base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableWebSecurity); + network::mojom::URLResponseHeadPtr response = network::mojom::URLResponseHead::New(); + response->response_type = network::cors::CalculateResponseType( + request.mode, disable_web_security || ( + request.request_initiator && request.request_initiator->IsSameOriginWith(url::Origin::Create(request.url)))); + + return response; + } +} + namespace QtWebEngineCore { +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeMainFrame, blink::mojom::ResourceType::kMainFrame) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeSubFrame, blink::mojom::ResourceType::kSubFrame) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeStylesheet, blink::mojom::ResourceType::kStylesheet) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeScript, blink::mojom::ResourceType::kScript) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeImage, blink::mojom::ResourceType::kImage) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeFontResource, blink::mojom::ResourceType::kFontResource) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeSubResource, blink::mojom::ResourceType::kSubResource) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeObject, blink::mojom::ResourceType::kObject) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeMedia, blink::mojom::ResourceType::kMedia) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeWorker, blink::mojom::ResourceType::kWorker) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeSharedWorker, blink::mojom::ResourceType::kSharedWorker) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypePrefetch, blink::mojom::ResourceType::kPrefetch) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeFavicon, blink::mojom::ResourceType::kFavicon) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeXhr, blink::mojom::ResourceType::kXhr) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypePing, blink::mojom::ResourceType::kPing) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeServiceWorker, blink::mojom::ResourceType::kServiceWorker) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeCspReport, blink::mojom::ResourceType::kCspReport) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypePluginResource, blink::mojom::ResourceType::kPluginResource) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeNavigationPreloadMainFrame, blink::mojom::ResourceType::kNavigationPreloadMainFrame) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeNavigationPreloadSubFrame, blink::mojom::ResourceType::kNavigationPreloadSubFrame) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeLast, blink::mojom::ResourceType::kMaxValue) + extern WebContentsAdapterClient::NavigationType pageTransitionToNavigationType(ui::PageTransition transition); -static QWebEngineUrlRequestInfo::ResourceType toQt(content::ResourceType resourceType) +static QWebEngineUrlRequestInfo::ResourceType toQt(blink::mojom::ResourceType resourceType) { - if (resourceType >= content::ResourceType::kMainFrame && resourceType <= content::ResourceType::kMaxValue) + if (resourceType >= blink::mojom::ResourceType::kMinValue && resourceType <= blink::mojom::ResourceType::kMaxValue) return static_cast<QWebEngineUrlRequestInfo::ResourceType>(resourceType); return QWebEngineUrlRequestInfo::ResourceTypeUnknown; } @@ -95,20 +122,20 @@ class InterceptedRequest : public network::mojom::URLLoader , public network::mojom::URLLoaderClient { public: - InterceptedRequest(int process_id, uint64_t request_id, int32_t routing_id, uint32_t options, + InterceptedRequest(ProfileAdapter *profile_adapter, + int process_id, uint64_t request_id, int32_t routing_id, uint32_t options, const network::ResourceRequest &request, const net::MutableNetworkTrafficAnnotationTag &traffic_annotation, - ProfileIODataQt *profileData, - network::mojom::URLLoaderRequest loader_request, network::mojom::URLLoaderClientPtr client, - network::mojom::URLLoaderFactoryPtr target_factory); + mojo::PendingReceiver<network::mojom::URLLoader> loader, + mojo::PendingRemote<network::mojom::URLLoaderClient> client, + mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory); ~InterceptedRequest() override; void Restart(); - void InterceptOnUIThread(); // network::mojom::URLLoaderClient - void OnReceiveResponse(const network::ResourceResponseHead &head) override; - void OnReceiveRedirect(const net::RedirectInfo &redirect_info, const network::ResourceResponseHead &head) override; + void OnReceiveResponse(network::mojom::URLResponseHeadPtr head) override; + void OnReceiveRedirect(const net::RedirectInfo &redirect_info, network::mojom::URLResponseHeadPtr head) override; void OnUploadProgress(int64_t current_position, int64_t total_size, OnUploadProgressCallback callback) override; void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override; void OnTransferSizeUpdated(int32_t transfer_size_diff) override; @@ -117,15 +144,17 @@ public: // network::mojom::URLLoader void FollowRedirect(const std::vector<std::string> &removed_headers, - const net::HttpRequestHeaders &modified_headers, const base::Optional<GURL> &new_url) override; - void ProceedWithResponse() override; + const net::HttpRequestHeaders &modified_headers, + const net::HttpRequestHeaders &modified_cors_exempt_headers, + const base::Optional<GURL> &new_url) override; void SetPriority(net::RequestPriority priority, int32_t intra_priority_value) override; void PauseReadingBodyFromNet() override; void ResumeReadingBodyFromNet() override; + void InterceptOnUIThread(QWebEngineUrlRequestInterceptor *profileInterceptor); + void InterceptOnIOThread(base::WaitableEvent *event, QWebEngineUrlRequestInterceptor *profileInterceptor); void ContinueAfterIntercept(); -private: // This is called when the original URLLoaderClient has a connection error. void OnURLLoaderClientError(); @@ -139,158 +168,227 @@ private: void SendErrorAndCompleteImmediately(int error_code); + content::WebContents* webContents(); + QWebEngineUrlRequestInterceptor* getProfileInterceptor(); + QWebEngineUrlRequestInterceptor* getPageInterceptor(); + + QPointer<ProfileAdapter> profile_adapter_; const int process_id_; const uint64_t request_id_; const int32_t routing_id_; const uint32_t options_; - bool input_stream_previously_failed_ = false; - bool request_was_redirected_ = false; + bool allowed_cors_ = true; + + bool loader_error_seen_ = false; // If the |target_loader_| called OnComplete with an error this stores it. // That way the destructor can send it to OnReceivedError if safe browsing // error didn't occur. int error_status_ = net::OK; - GURL m_originalUrl; - network::ResourceRequest request_; - network::ResourceResponseHead current_response_; + network::mojom::URLResponseHeadPtr current_response_; const net::MutableNetworkTrafficAnnotationTag traffic_annotation_; - ProfileIODataQt *m_profileData; - mojo::Binding<network::mojom::URLLoader> proxied_loader_binding_; - network::mojom::URLLoaderClientPtr target_client_; + static inline void cleanup(QWebEngineUrlRequestInfo *info) { delete info; } + QScopedPointer<QWebEngineUrlRequestInfo, InterceptedRequest> request_info_; - mojo::Binding<network::mojom::URLLoaderClient> proxied_client_binding_; - network::mojom::URLLoaderPtr target_loader_; - network::mojom::URLLoaderFactoryPtr target_factory_; + mojo::Receiver<network::mojom::URLLoader> proxied_loader_receiver_; + mojo::Remote<network::mojom::URLLoaderClient> target_client_; + mojo::Receiver<network::mojom::URLLoaderClient> proxied_client_receiver_{this}; + mojo::Remote<network::mojom::URLLoader> target_loader_; + mojo::Remote<network::mojom::URLLoaderFactory> target_factory_; - base::WeakPtrFactory<InterceptedRequest> m_weakFactory; - base::WeakPtr<InterceptedRequest> m_weakPtr; + base::WeakPtrFactory<InterceptedRequest> weak_factory_; DISALLOW_COPY_AND_ASSIGN(InterceptedRequest); }; -InterceptedRequest::InterceptedRequest(int process_id, uint64_t request_id, int32_t routing_id, uint32_t options, +InterceptedRequest::InterceptedRequest(ProfileAdapter *profile_adapter, + int process_id, uint64_t request_id, int32_t routing_id, uint32_t options, const network::ResourceRequest &request, const net::MutableNetworkTrafficAnnotationTag &traffic_annotation, - ProfileIODataQt *profileData, - network::mojom::URLLoaderRequest loader_request, - network::mojom::URLLoaderClientPtr client, - network::mojom::URLLoaderFactoryPtr target_factory) - : process_id_(process_id) + mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver, + mojo::PendingRemote<network::mojom::URLLoaderClient> client, + mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory) + : profile_adapter_(profile_adapter) + , process_id_(process_id) , request_id_(request_id) , routing_id_(routing_id) , options_(options) , request_(request) , traffic_annotation_(traffic_annotation) - , m_profileData(profileData) - , proxied_loader_binding_(this, std::move(loader_request)) + , proxied_loader_receiver_(this, std::move(loader_receiver)) , target_client_(std::move(client)) - , proxied_client_binding_(this) , target_factory_(std::move(target_factory)) - , m_weakFactory(this) - , m_weakPtr(m_weakFactory.GetWeakPtr()) + , weak_factory_(this) { + const bool disable_web_security = base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableWebSecurity); + current_response_ = createResponse(request_); // If there is a client error, clean up the request. - target_client_.set_connection_error_handler( - base::BindOnce(&InterceptedRequest::OnURLLoaderClientError, m_weakFactory.GetWeakPtr())); - proxied_loader_binding_.set_connection_error_with_reason_handler( - base::BindOnce(&InterceptedRequest::OnURLLoaderError, m_weakFactory.GetWeakPtr())); + target_client_.set_disconnect_handler( + base::BindOnce(&InterceptedRequest::OnURLLoaderClientError, base::Unretained(this))); + proxied_loader_receiver_.set_disconnect_with_reason_handler( + base::BindOnce(&InterceptedRequest::OnURLLoaderError, base::Unretained(this))); + if (!disable_web_security && request_.request_initiator) { + const std::vector<std::string> &localSchemes = url::GetLocalSchemes(); + std::string fromScheme = request_.request_initiator->GetTupleOrPrecursorTupleIfOpaque().scheme(); + if (base::Contains(localSchemes, fromScheme)) { + content::WebContents *wc = webContents(); + std::string toScheme = request_.url.scheme(); + // local schemes must have universal access, or be accessing something local and have local access. + if (fromScheme != toScheme) { + // note allow_file_access_from_file_urls maps to LocalContentCanAccessFileUrls in our API + // and allow_universal_access_from_file_urls to LocalContentCanAccessRemoteUrls, so we are + // using them as proxies for our API here. + if (toScheme == "file") + allowed_cors_ = wc && wc->GetOrCreateWebPreferences().allow_file_access_from_file_urls; + else if (!base::Contains(localSchemes, toScheme)) + allowed_cors_ = wc && wc->GetOrCreateWebPreferences().allow_universal_access_from_file_urls; + else + allowed_cors_ = true; // We should think about this for future patches + } + } + } } InterceptedRequest::~InterceptedRequest() { - m_weakFactory.InvalidateWeakPtrs(); + weak_factory_.InvalidateWeakPtrs(); } -void InterceptedRequest::Restart() +content::WebContents* InterceptedRequest::webContents() +{ + if (process_id_) { + content::RenderFrameHost *frameHost = content::RenderFrameHost::FromID(process_id_, request_.render_frame_id); + return content::WebContents::FromRenderFrameHost(frameHost); + } + + return content::WebContents::FromFrameTreeNodeId(request_.render_frame_id); +} + +QWebEngineUrlRequestInterceptor* InterceptedRequest::getProfileInterceptor() { - // FIXME: Support deprecated interceptors here + return profile_adapter_ ? profile_adapter_->requestInterceptor() : nullptr; +} - // FIXME: unretained post? - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&InterceptedRequest::InterceptOnUIThread, base::Unretained(this))); +QWebEngineUrlRequestInterceptor* InterceptedRequest::getPageInterceptor() +{ + if (auto wc = webContents()) { + auto view = static_cast<content::WebContentsImpl *>(wc)->GetView(); + if (WebContentsAdapterClient *client = WebContentsViewQt::from(view)->client()) + return client->webContentsAdapter()->requestInterceptor(); + } + return nullptr; } -void InterceptedRequest::InterceptOnUIThread() +void InterceptedRequest::Restart() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - content::ResourceType resourceType = content::ResourceType(request_.resource_type); - WebContentsAdapterClient::NavigationType navigationType = - pageTransitionToNavigationType(ui::PageTransition(request_.transition_type)); + // This is a CORS check on the from URL, the normal check on the to URL is applied later + if (!allowed_cors_ && current_response_->response_type == network::mojom::FetchResponseType::kCors) { + target_client_->OnComplete(network::URLLoaderCompletionStatus( + network::CorsErrorStatus(network::mojom::CorsError::kCorsDisabledScheme))); + delete this; + return; + } - m_originalUrl = request_.url; - const QUrl qUrl = toQt(request_.url); + // MEMO since all codepatch leading to Restart scheduled and executed as asynchronous tasks in main thread, + // interceptors may change in meantime and also during intercept call, so they should be resolved anew. + // Set here only profile's interceptor since it runs first without going to user code. + auto profileInterceptor = getProfileInterceptor(); + if (!profileInterceptor && !getPageInterceptor()) { + ContinueAfterIntercept(); + return; + } + auto resourceType = toQt(blink::mojom::ResourceType(request_.resource_type)); + auto navigationType = toQt(pageTransitionToNavigationType(ui::PageTransition(request_.transition_type))); + const QUrl originalUrl = toQt(request_.url); const QUrl initiator = request_.request_initiator.has_value() ? toQt(request_.request_initiator->GetURL()) : QUrl(); + auto wc = webContents(); + GURL top_document_url = wc ? wc->GetVisibleURL() : GURL(); QUrl firstPartyUrl; - if (resourceType == content::ResourceType::kSubFrame) - firstPartyUrl = toQt(request_.first_party_url); + if (!top_document_url.is_empty()) + firstPartyUrl = toQt(top_document_url); else - firstPartyUrl = toQt(request_.site_for_cookies); + firstPartyUrl = toQt(request_.site_for_cookies.first_party_url()); // m_topDocumentUrl can be empty for the main-frame. + + auto info = new QWebEngineUrlRequestInfoPrivate(resourceType, navigationType, originalUrl, firstPartyUrl, + initiator, QByteArray::fromStdString(request_.method)); + Q_ASSERT(!request_info_); + request_info_.reset(new QWebEngineUrlRequestInfo(info)); + + // TODO: remove for Qt6 + bool isDeprecatedProfileInterceptor = profileInterceptor == nullptr; + if (profileInterceptor && profileInterceptor->property("deprecated").toBool()) { + isDeprecatedProfileInterceptor = true; + // sync call supports depracated call of an interceptor on io thread + base::WaitableEvent event; + base::PostTask(FROM_HERE, { content::BrowserThread::IO }, + base::BindOnce(&InterceptedRequest::InterceptOnIOThread, + base::Unretained(this), &event, profileInterceptor)); + event.Wait(); + if (request_info_->changed()) { + ContinueAfterIntercept(); + return; + } + } + InterceptOnUIThread(isDeprecatedProfileInterceptor ? nullptr : profileInterceptor); + ContinueAfterIntercept(); +} - QWebEngineUrlRequestInfoPrivate *infoPrivate = new QWebEngineUrlRequestInfoPrivate(toQt(resourceType), - toQt(navigationType), - qUrl, - firstPartyUrl, - initiator, - QByteArray::fromStdString(request_.method)); - QWebEngineUrlRequestInfo requestInfo(infoPrivate); +void InterceptedRequest::InterceptOnIOThread(base::WaitableEvent *event, QWebEngineUrlRequestInterceptor *interceptor) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + interceptor->interceptRequest(*request_info_); + event->Signal(); +} - content::WebContents *webContents = nullptr; - if (process_id_) { - content::RenderFrameHost *frameHost = content::RenderFrameHost::FromID(process_id_, request_.render_frame_id); - webContents = content::WebContents::FromRenderFrameHost(frameHost); - } else - webContents = content::WebContents::FromFrameTreeNodeId(request_.render_frame_id); - - if (webContents) { - int result = net::OK; - if (m_profileData) { - QWebEngineUrlRequestInterceptor *interceptor = m_profileData->requestInterceptor(); - if (interceptor && !interceptor->property("deprecated").toBool()) - interceptor->interceptRequest(requestInfo); - } +void InterceptedRequest::InterceptOnUIThread(QWebEngineUrlRequestInterceptor *profileInterceptor) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (profileInterceptor) + profileInterceptor->interceptRequest(*request_info_); - WebContentsAdapterClient *client = - WebContentsViewQt::from(static_cast<content::WebContentsImpl*>(webContents)->GetView())->client(); + if (!request_info_->changed()) { + if (auto interceptor = getPageInterceptor()) + interceptor->interceptRequest(*request_info_); + } +} - if (!requestInfo.changed()) { - client->interceptRequest(requestInfo); - } +void InterceptedRequest::ContinueAfterIntercept() +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - if (requestInfo.changed()) { - result = requestInfo.d_ptr->shouldBlockRequest ? net::ERR_BLOCKED_BY_CLIENT : net::OK; - // We handle the rest of the changes later when we are back in I/O thread - } + if (request_info_) { + // cleanup in scope because of delete this and it's not needed else where after + decltype(request_info_) scoped_request_info(request_info_.take()); + QWebEngineUrlRequestInfoPrivate &info = *scoped_request_info->d_ptr; + + if (info.changed) { + if (info.shouldBlockRequest) + return SendErrorAndCompleteImmediately(net::ERR_BLOCKED_BY_CLIENT); + + for (auto header = info.extraHeaders.constBegin(); header != info.extraHeaders.constEnd(); ++header) { + std::string h = header.key().toStdString(); + if (base::LowerCaseEqualsASCII(h, "referer")) { + request_.referrer = GURL(header.value().toStdString()); + } else { + request_.headers.SetHeader(h, header.value().toStdString()); + } + } - if (result != net::OK) { - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&InterceptedRequest::SendErrorAndCompleteImmediately, m_weakPtr, result)); - return; - } - if (requestInfo.changed()) { - if (requestInfo.requestUrl() != qUrl) { - net::URLRequest::FirstPartyURLPolicy first_party_url_policy = - request_.update_first_party_url_on_redirect ? net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT - : net::URLRequest::NEVER_CHANGE_FIRST_PARTY_URL; - net::RedirectInfo redirectInfo = net::RedirectInfo::ComputeRedirectInfo(request_.method, request_.url, - request_.site_for_cookies, request_.top_frame_origin, - first_party_url_policy, request_.referrer_policy, - request_.referrer.spec(), net::HTTP_TEMPORARY_REDIRECT, - toGurl(requestInfo.requestUrl()), base::nullopt, - false /*insecure_scheme_was_upgraded*/); - - // FIXME: Should probably create a new header. - current_response_.encoded_data_length = 0; - // FIXME: unretained post. - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&network::mojom::URLLoaderClientProxy::OnReceiveRedirect, base::Unretained(&(*target_client_)), redirectInfo, current_response_)); + if (info.shouldRedirectRequest) { + net::RedirectInfo::FirstPartyURLPolicy first_party_url_policy = + request_.update_first_party_url_on_redirect ? net::RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT + : net::RedirectInfo::FirstPartyURLPolicy::NEVER_CHANGE_URL; + net::RedirectInfo redirectInfo = net::RedirectInfo::ComputeRedirectInfo( + request_.method, request_.url, request_.site_for_cookies, + first_party_url_policy, request_.referrer_policy, request_.referrer.spec(), + net::HTTP_TEMPORARY_REDIRECT, toGurl(info.url), base::nullopt, + false /*insecure_scheme_was_upgraded*/); request_.method = redirectInfo.new_method; request_.url = redirectInfo.new_url; request_.site_for_cookies = redirectInfo.new_site_for_cookies; @@ -298,53 +396,39 @@ void InterceptedRequest::InterceptOnUIThread() request_.referrer_policy = redirectInfo.new_referrer_policy; if (request_.method == net::HttpRequestHeaders::kGetMethod) request_.request_body = nullptr; + // In case of multiple sequential rediredts, current_response_ has previously been moved to target_client_ + // so we create a new one using the redirect url. + if (!current_response_) + current_response_ = createResponse(request_); + current_response_->encoded_data_length = 0; + target_client_->OnReceiveRedirect(redirectInfo, std::move(current_response_)); return; } - - if (!requestInfo.d_ptr->extraHeaders.isEmpty()) { - auto end = requestInfo.d_ptr->extraHeaders.constEnd(); - for (auto header = requestInfo.d_ptr->extraHeaders.constBegin(); header != end; ++header) { - std::string h = header.key().toStdString(); - if (base::LowerCaseEqualsASCII(h, "referer")) { - request_.referrer = GURL(header.value().toStdString()); - } else { - request_.headers.SetHeader(h, header.value().toStdString()); - } - } - } } } - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&InterceptedRequest::ContinueAfterIntercept, m_weakPtr)); -} -void InterceptedRequest::ContinueAfterIntercept() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (!target_loader_ && target_factory_) { - network::mojom::URLLoaderClientPtr proxied_client; - proxied_client_binding_.Bind(mojo::MakeRequest(&proxied_client)); - target_factory_->CreateLoaderAndStart(mojo::MakeRequest(&target_loader_), routing_id_, request_id_, options_, - request_, std::move(proxied_client), traffic_annotation_); + loader_error_seen_ = false; + target_factory_->CreateLoaderAndStart(target_loader_.BindNewPipeAndPassReceiver(), routing_id_, request_id_, + options_, request_, proxied_client_receiver_.BindNewPipeAndPassRemote(), + traffic_annotation_); } } // URLLoaderClient methods. -void InterceptedRequest::OnReceiveResponse(const network::ResourceResponseHead &head) +void InterceptedRequest::OnReceiveResponse(network::mojom::URLResponseHeadPtr head) { - current_response_ = head; + current_response_ = head.Clone(); - target_client_->OnReceiveResponse(head); + target_client_->OnReceiveResponse(std::move(head)); } -void InterceptedRequest::OnReceiveRedirect(const net::RedirectInfo &redirect_info, const network::ResourceResponseHead &head) +void InterceptedRequest::OnReceiveRedirect(const net::RedirectInfo &redirect_info, network::mojom::URLResponseHeadPtr head) { // TODO(timvolodine): handle redirect override. - request_was_redirected_ = true; - current_response_ = head; - target_client_->OnReceiveRedirect(redirect_info, head); + current_response_ = head.Clone(); + target_client_->OnReceiveRedirect(redirect_info, std::move(head)); request_.url = redirect_info.new_url; request_.method = redirect_info.new_method; request_.site_for_cookies = redirect_info.new_site_for_cookies; @@ -384,10 +468,11 @@ void InterceptedRequest::OnComplete(const network::URLLoaderCompletionStatus &st void InterceptedRequest::FollowRedirect(const std::vector<std::string> &removed_headers, const net::HttpRequestHeaders &modified_headers, + const net::HttpRequestHeaders &modified_cors_exempt_headers, const base::Optional<GURL> &new_url) { if (target_loader_) - target_loader_->FollowRedirect(removed_headers, modified_headers, new_url); + target_loader_->FollowRedirect(removed_headers, modified_headers, modified_cors_exempt_headers, new_url); // If |OnURLLoaderClientError| was called then we're just waiting for the // connection error handler of |proxied_loader_binding_|. Don't restart the @@ -398,12 +483,6 @@ void InterceptedRequest::FollowRedirect(const std::vector<std::string> &removed_ Restart(); } -void InterceptedRequest::ProceedWithResponse() -{ - if (target_loader_) - target_loader_->ProceedWithResponse(); -} - void InterceptedRequest::SetPriority(net::RequestPriority priority, int32_t intra_priority_value) { if (target_loader_) @@ -435,11 +514,13 @@ void InterceptedRequest::OnURLLoaderError(uint32_t custom_reason, const std::str // If CallOnComplete was already called, then this object is ready to be deleted. if (!target_client_) delete this; + else + loader_error_seen_ = true; } void InterceptedRequest::CallOnComplete(const network::URLLoaderCompletionStatus &status, bool wait_for_loader_error) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // Save an error status so that we call onReceiveError at destruction if there // was no safe browsing error. if (status.error_code != net::OK) @@ -448,22 +529,22 @@ void InterceptedRequest::CallOnComplete(const network::URLLoaderCompletionStatus if (target_client_) target_client_->OnComplete(status); - if (proxied_loader_binding_ && wait_for_loader_error) { - // Don't delete |this| yet, in case the |proxied_loader_binding_|'s + if (proxied_loader_receiver_.is_bound() && wait_for_loader_error && !loader_error_seen_) { + // Since the original client is gone no need to continue loading the + // request. + proxied_client_receiver_.reset(); + target_loader_.reset(); + + // Don't delete |this| yet, in case the |proxied_loader_receiver_|'s // error_handler is called with a reason to indicate an error which we want // to send to the client bridge. Also reset |target_client_| so we don't // get its error_handler called and then delete |this|. target_client_.reset(); - // Since the original client is gone no need to continue loading the - // request. - proxied_client_binding_.Close(); - target_loader_.reset(); - // In case there are pending checks as to whether this request should be // intercepted, we don't want that causing |target_client_| to be used // later. - m_weakFactory.InvalidateWeakPtrs(); + weak_factory_.InvalidateWeakPtrs(); } else { delete this; } @@ -471,26 +552,25 @@ void InterceptedRequest::CallOnComplete(const network::URLLoaderCompletionStatus void InterceptedRequest::SendErrorAndCompleteImmediately(int error_code) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); auto status = network::URLLoaderCompletionStatus(error_code); target_client_->OnComplete(status); delete this; } -ProxyingURLLoaderFactoryQt::ProxyingURLLoaderFactoryQt(int process_id, - content::ResourceContext *resourceContext, - network::mojom::URLLoaderFactoryRequest loader_request, - network::mojom::URLLoaderFactoryPtrInfo target_factory_info) - : m_processId(process_id), m_resourceContext(resourceContext), m_weakFactory(this) +ProxyingURLLoaderFactoryQt::ProxyingURLLoaderFactoryQt(ProfileAdapter *adapter, int process_id, + mojo::PendingReceiver<network::mojom::URLLoaderFactory> loader_receiver, + mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory_info) + : m_profileAdapter(adapter), m_processId(process_id), m_weakFactory(this) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (target_factory_info) { m_targetFactory.Bind(std::move(target_factory_info)); - m_targetFactory.set_connection_error_handler( + m_targetFactory.set_disconnect_handler( base::BindOnce(&ProxyingURLLoaderFactoryQt::OnTargetFactoryError, m_weakFactory.GetWeakPtr())); } - m_proxyBindings.AddBinding(this, std::move(loader_request)); - m_proxyBindings.set_connection_error_handler( + m_proxyReceivers.Add(this, std::move(loader_receiver)); + m_proxyReceivers.set_disconnect_handler( base::BindRepeating(&ProxyingURLLoaderFactoryQt::OnProxyBindingError, m_weakFactory.GetWeakPtr())); } @@ -499,46 +579,20 @@ ProxyingURLLoaderFactoryQt::~ProxyingURLLoaderFactoryQt() m_weakFactory.InvalidateWeakPtrs(); } -// static -void ProxyingURLLoaderFactoryQt::CreateProxy(int process_id, - content::ResourceContext *resourceContext, - network::mojom::URLLoaderFactoryRequest loader_request, - network::mojom::URLLoaderFactoryPtrInfo target_factory_info) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - // Will manage its own lifetime - new ProxyingURLLoaderFactoryQt(process_id, resourceContext, std::move(loader_request), std::move(target_factory_info)); -} - -void ProxyingURLLoaderFactoryQt::CreateLoaderAndStart(network::mojom::URLLoaderRequest loader, int32_t routing_id, - int32_t request_id, uint32_t options, - const network::ResourceRequest &request, - network::mojom::URLLoaderClientPtr client, +void ProxyingURLLoaderFactoryQt::CreateLoaderAndStart(mojo::PendingReceiver<network::mojom::URLLoader> loader, int32_t routing_id, + int32_t request_id, uint32_t options, const network::ResourceRequest &request, + mojo::PendingRemote<network::mojom::URLLoaderClient> url_loader_client, const net::MutableNetworkTrafficAnnotationTag &traffic_annotation) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - ProfileIODataQt *profileIOData = ProfileIODataQt::FromResourceContext(m_resourceContext); - - QWebEngineUrlRequestInterceptor *profileInterceptor = profileIOData ? profileIOData->requestInterceptor() : nullptr; - if (!profileIOData || !(profileInterceptor || profileIOData->hasPageInterceptors())) { - m_targetFactory->CreateLoaderAndStart( - std::move(loader), routing_id, request_id, options, request, - std::move(client), traffic_annotation); - return; - } - - network::mojom::URLLoaderFactoryPtr target_factory_clone; + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory_clone; if (m_targetFactory) - m_targetFactory->Clone(mojo::MakeRequest(&target_factory_clone)); - + m_targetFactory->Clone(target_factory_clone.InitWithNewPipeAndPassReceiver()); // Will manage its own lifetime - InterceptedRequest *req = new InterceptedRequest(m_processId, request_id, routing_id, options, request, - traffic_annotation, profileIOData, - std::move(loader), std::move(client), - std::move(target_factory_clone)); + InterceptedRequest *req = new InterceptedRequest(m_profileAdapter, m_processId, request_id, routing_id, options, + request, traffic_annotation, std::move(loader), + std::move(url_loader_client), std::move(target_factory_clone)); req->Restart(); } @@ -549,14 +603,14 @@ void ProxyingURLLoaderFactoryQt::OnTargetFactoryError() void ProxyingURLLoaderFactoryQt::OnProxyBindingError() { - if (m_proxyBindings.empty()) + if (m_proxyReceivers.empty()) delete this; } -void ProxyingURLLoaderFactoryQt::Clone(network::mojom::URLLoaderFactoryRequest loader_request) +void ProxyingURLLoaderFactoryQt::Clone(mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - m_proxyBindings.AddBinding(this, std::move(loader_request)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + m_proxyReceivers.Add(this, std::move(receiver)); } } // namespace QtWebEngineCore diff --git a/src/core/net/proxying_url_loader_factory_qt.h b/src/core/net/proxying_url_loader_factory_qt.h index a2f175885..5345e3220 100644 --- a/src/core/net/proxying_url_loader_factory_qt.h +++ b/src/core/net/proxying_url_loader_factory_qt.h @@ -42,61 +42,48 @@ #include "base/callback.h" #include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/ref_counted_delete_on_sequence.h" #include "base/memory/weak_ptr.h" -#include "base/optional.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/binding_set.h" +#include "mojo/public/cpp/bindings/receiver_set.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "services/network/public/cpp/resource_request.h" -#include "services/network/public/cpp/resource_response.h" #include "services/network/public/mojom/url_loader.mojom.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" -#include "url/gurl.h" +#include <QPointer> // based on aw_proxying_url_loader_factory.h: // Copyright 2018 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -namespace content { -class ResourceContext; -} - namespace QtWebEngineCore { +class ProfileAdapter; + class ProxyingURLLoaderFactoryQt : public network::mojom::URLLoaderFactory { public: - ProxyingURLLoaderFactoryQt(int process_id, content::ResourceContext *resourceContext, - network::mojom::URLLoaderFactoryRequest loader_request, - network::mojom::URLLoaderFactoryPtrInfo target_factory_info); + ProxyingURLLoaderFactoryQt(ProfileAdapter *adapter, int processId, + mojo::PendingReceiver<network::mojom::URLLoaderFactory> loader_receiver, + mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_target_factory_remote); ~ProxyingURLLoaderFactoryQt() override; - // static - static void CreateProxy(int process_id, content::ResourceContext *resourceContext, - network::mojom::URLLoaderFactoryRequest loader, - network::mojom::URLLoaderFactoryPtrInfo target_factory_info); - - void CreateLoaderAndStart(network::mojom::URLLoaderRequest loader, int32_t routing_id, int32_t request_id, + void CreateLoaderAndStart(mojo::PendingReceiver<network::mojom::URLLoader> loader, + int32_t routing_id, int32_t request_id, uint32_t options, const network::ResourceRequest &request, - network::mojom::URLLoaderClientPtr client, + mojo::PendingRemote<network::mojom::URLLoaderClient> client, const net::MutableNetworkTrafficAnnotationTag &traffic_annotation) override; - void Clone(network::mojom::URLLoaderFactoryRequest loader_request) override; + void Clone(mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) override; private: void OnTargetFactoryError(); void OnProxyBindingError(); - const int m_processId; - mojo::BindingSet<network::mojom::URLLoaderFactory> m_proxyBindings; - network::mojom::URLLoaderFactoryPtr m_targetFactory; - - content::ResourceContext *m_resourceContext; - + QPointer<ProfileAdapter> m_profileAdapter; + int m_processId; + mojo::ReceiverSet<network::mojom::URLLoaderFactory> m_proxyReceivers; + mojo::Remote<network::mojom::URLLoaderFactory> m_targetFactory; base::WeakPtrFactory<ProxyingURLLoaderFactoryQt> m_weakFactory; DISALLOW_COPY_AND_ASSIGN(ProxyingURLLoaderFactoryQt); diff --git a/src/core/net/qrc_url_scheme_handler.cpp b/src/core/net/qrc_url_scheme_handler.cpp index 73bf24f1d..0a9943431 100644 --- a/src/core/net/qrc_url_scheme_handler.cpp +++ b/src/core/net/qrc_url_scheme_handler.cpp @@ -67,7 +67,10 @@ void QrcUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *job) QFileInfo fileInfo(*file); QMimeDatabase mimeDatabase; QMimeType mimeType = mimeDatabase.mimeTypeForFile(fileInfo); - job->reply(mimeType.name().toUtf8(), file.take()); + if (mimeType.name() == QStringLiteral("application/x-extension-html")) + job->reply("text/html", file.take()); + else + job->reply(mimeType.name().toUtf8(), file.take()); } } // namespace QtWebEngineCore diff --git a/src/core/net/restricted_cookie_manager_qt.cpp b/src/core/net/restricted_cookie_manager_qt.cpp deleted file mode 100644 index 7f1ca163e..000000000 --- a/src/core/net/restricted_cookie_manager_qt.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// originally based on android_webview/browser/network_service/aw_proxying_restricted_cookie_manager.cc: -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "restricted_cookie_manager_qt.h" - -#include "api/qwebenginecookiestore.h" -#include "api/qwebenginecookiestore_p.h" -#include "profile_adapter.h" -#include "profile_qt.h" -#include "type_conversion.h" - -#include "base/memory/ptr_util.h" -#include "base/task/post_task.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" -#include "mojo/public/cpp/bindings/strong_binding.h" - -namespace QtWebEngineCore { - -class RestrictedCookieManagerListenerQt : public network::mojom::CookieChangeListener -{ -public: - RestrictedCookieManagerListenerQt(const GURL &url, - const GURL &site_for_cookies, - base::WeakPtr<RestrictedCookieManagerQt> restricted_cookie_manager, - network::mojom::CookieChangeListenerPtr client_listener) - : url_(url) - , site_for_cookies_(site_for_cookies) - , restricted_cookie_manager_(restricted_cookie_manager) - , client_listener_(std::move(client_listener)) - {} - - void OnCookieChange(const net::CanonicalCookie &cookie, network::mojom::CookieChangeCause cause) override - { - if (restricted_cookie_manager_ && restricted_cookie_manager_->allowCookies(url_, site_for_cookies_)) - client_listener_->OnCookieChange(cookie, cause); - } - -private: - const GURL url_; - const GURL site_for_cookies_; - base::WeakPtr<RestrictedCookieManagerQt> restricted_cookie_manager_; - network::mojom::CookieChangeListenerPtr client_listener_; -}; - -RestrictedCookieManagerQt::RestrictedCookieManagerQt(base::WeakPtr<ProfileIODataQt> profileIoData, - network::mojom::RestrictedCookieManagerRole role, - net::CookieStore *cookie_store, - network::CookieSettings *cookie_settings, - const url::Origin &origin, - bool is_service_worker, - int32_t process_id, - int32_t frame_id) - : network::RestrictedCookieManager(role, cookie_store, cookie_settings, origin, - nullptr, is_service_worker, process_id, frame_id) - , m_profileIoData(profileIoData) - , weak_factory_(this) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); -} - -RestrictedCookieManagerQt::~RestrictedCookieManagerQt() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); -} - -void RestrictedCookieManagerQt::GetAllForUrl(const GURL &url, - const GURL &site_for_cookies, - network::mojom::CookieManagerGetOptionsPtr options, - GetAllForUrlCallback callback) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - if (allowCookies(url, site_for_cookies)) { - network::RestrictedCookieManager::GetAllForUrl(url, site_for_cookies, std::move(options), std::move(callback)); - } else { - std::move(callback).Run(std::vector<net::CanonicalCookie>()); - } -} - -void RestrictedCookieManagerQt::SetCanonicalCookie(const net::CanonicalCookie &cookie, - const GURL &url, - const GURL &site_for_cookies, - SetCanonicalCookieCallback callback) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - if (allowCookies(url, site_for_cookies)) { - network::RestrictedCookieManager::SetCanonicalCookie(cookie, url, site_for_cookies, std::move(callback)); - } else { - std::move(callback).Run(false); - } -} - -void RestrictedCookieManagerQt::AddChangeListener(const GURL &url, - const GURL &site_for_cookies, - network::mojom::CookieChangeListenerPtr listener, - AddChangeListenerCallback callback) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - network::mojom::CookieChangeListenerPtr proxy_listener_ptr; - auto proxy_listener = - std::make_unique<RestrictedCookieManagerListenerQt>( - url, site_for_cookies, weak_factory_.GetWeakPtr(), - std::move(listener)); - - mojo::MakeStrongBinding(std::move(proxy_listener), - mojo::MakeRequest(&proxy_listener_ptr)); - - network::RestrictedCookieManager::AddChangeListener( - url, site_for_cookies, std::move(proxy_listener_ptr), - std::move(callback)); -} - -void RestrictedCookieManagerQt::GetCookiesString(const GURL &url, - const GURL &site_for_cookies, - GetCookiesStringCallback callback) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - if (allowCookies(url, site_for_cookies)) { - network::RestrictedCookieManager::GetCookiesString(url, site_for_cookies, std::move(callback)); - } else { - std::move(callback).Run(""); - } -} - -void RestrictedCookieManagerQt::CookiesEnabledFor(const GURL &url, - const GURL &site_for_cookies, - CookiesEnabledForCallback callback) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - std::move(callback).Run(allowCookies(url, site_for_cookies)); -} - -bool RestrictedCookieManagerQt::allowCookies(const GURL &url, const GURL &site_for_cookies) const -{ - if (!m_profileIoData) - return false; - return m_profileIoData->canGetCookies(toQt(site_for_cookies), toQt(url)); -} - -} // namespace QtWebEngineCore diff --git a/src/core/net/restricted_cookie_manager_qt.h b/src/core/net/restricted_cookie_manager_qt.h deleted file mode 100644 index c135a1795..000000000 --- a/src/core/net/restricted_cookie_manager_qt.h +++ /dev/null @@ -1,100 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef RESTRICTED_COOKIE_MANAGER_QT_H -#define RESTRICTED_COOKIE_MANAGER_QT_H - -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "services/network/restricted_cookie_manager.h" -#include "url/gurl.h" - -namespace QtWebEngineCore { - -class ProfileIODataQt; - -class RestrictedCookieManagerQt : public network::RestrictedCookieManager -{ -public: - RestrictedCookieManagerQt(base::WeakPtr<ProfileIODataQt> profileIoData, - network::mojom::RestrictedCookieManagerRole role, - net::CookieStore *cookie_store, - network::CookieSettings *cookie_settings, - const url::Origin &origin, - bool is_service_worker, - int32_t process_id, - int32_t frame_id); - ~RestrictedCookieManagerQt() override; - - // network::RestrictedCookieManager: - void GetAllForUrl(const GURL &url, - const GURL &site_for_cookies, - network::mojom::CookieManagerGetOptionsPtr options, - GetAllForUrlCallback callback) override; - void SetCanonicalCookie(const net::CanonicalCookie& cookie, - const GURL &url, - const GURL &site_for_cookies, - SetCanonicalCookieCallback callback) override; - void AddChangeListener(const GURL &url, - const GURL &site_for_cookies, - network::mojom::CookieChangeListenerPtr listener, - AddChangeListenerCallback callback) override; - - void GetCookiesString(const GURL &url, - const GURL &site_for_cookies, - GetCookiesStringCallback callback) override; - - void CookiesEnabledFor(const GURL &url, - const GURL &site_for_cookies, - CookiesEnabledForCallback callback) override; - - // Internal: - bool allowCookies(const GURL &url, const GURL &site_for_cookies) const; - -private: - base::WeakPtr<ProfileIODataQt> m_profileIoData; - - base::WeakPtrFactory<RestrictedCookieManagerQt> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(RestrictedCookieManagerQt); -}; - -} // namespace QtWebEngineCore - -#endif // RESTRICTED_COOKIE_MANAGER_QT_H diff --git a/src/core/net/ssl_host_state_delegate_qt.cpp b/src/core/net/ssl_host_state_delegate_qt.cpp index 0885475be..3390c092a 100644 --- a/src/core/net/ssl_host_state_delegate_qt.cpp +++ b/src/core/net/ssl_host_state_delegate_qt.cpp @@ -77,13 +77,13 @@ SSLHostStateDelegateQt::SSLHostStateDelegateQt() {} SSLHostStateDelegateQt::~SSLHostStateDelegateQt() {} -void SSLHostStateDelegateQt::AllowCert(const std::string &host, const net::X509Certificate &cert, int error) +void SSLHostStateDelegateQt::AllowCert(const std::string &host, const net::X509Certificate &cert, int error, content::WebContents *) { m_certPolicyforHost[host].Allow(cert, error); } // Clear all allow preferences. -void SSLHostStateDelegateQt::Clear(const base::Callback<bool(const std::string &)> &host_filter) +void SSLHostStateDelegateQt::Clear(base::RepeatingCallback<bool(const std::string&)> host_filter) { if (host_filter.is_null()) { m_certPolicyforHost.clear(); @@ -105,8 +105,7 @@ void SSLHostStateDelegateQt::Clear(const base::Callback<bool(const std::string & // prior to this query, otherwise false. content::SSLHostStateDelegate::CertJudgment SSLHostStateDelegateQt::QueryPolicy(const std::string &host, const net::X509Certificate &cert, - int error, - bool * /*expired_previous_decision*/) + int error, content::WebContents *) { return m_certPolicyforHost[host].Check(cert, error) ? SSLHostStateDelegate::ALLOWED : SSLHostStateDelegate::DENIED; } @@ -133,7 +132,7 @@ void SSLHostStateDelegateQt::RevokeUserAllowExceptions(const std::string &host) // |host|. This does not mean that *all* certificate errors are allowed, just // that there exists an exception. To see if a particular certificate and // error combination exception is allowed, use QueryPolicy(). -bool SSLHostStateDelegateQt::HasAllowException(const std::string &host) +bool SSLHostStateDelegateQt::HasAllowException(const std::string &host, content::WebContents *) { auto policy_iterator = m_certPolicyforHost.find(host); return policy_iterator != m_certPolicyforHost.end() && diff --git a/src/core/net/ssl_host_state_delegate_qt.h b/src/core/net/ssl_host_state_delegate_qt.h index e361aa0be..6b407353a 100644 --- a/src/core/net/ssl_host_state_delegate_qt.h +++ b/src/core/net/ssl_host_state_delegate_qt.h @@ -66,14 +66,13 @@ public: ~SSLHostStateDelegateQt(); // content::SSLHostStateDelegate implementation: - void AllowCert(const std::string &, const net::X509Certificate &cert, int error) override; - void Clear(const base::Callback<bool(const std::string &)> &host_filter) override; - CertJudgment QueryPolicy(const std::string &host, const net::X509Certificate &cert, int error, - bool *expired_previous_decision) override; + void AllowCert(const std::string &, const net::X509Certificate &cert, int error, content::WebContents *web_contents) override; + void Clear(base::RepeatingCallback<bool(const std::string&)> host_filter) override; + CertJudgment QueryPolicy(const std::string &host, const net::X509Certificate &cert, int error, content::WebContents *web_contents) override; void HostRanInsecureContent(const std::string &host, int child_id, InsecureContentType content_type) override; bool DidHostRunInsecureContent(const std::string &host, int child_id, InsecureContentType content_type) override; void RevokeUserAllowExceptions(const std::string &host) override; - bool HasAllowException(const std::string &host) override; + bool HasAllowException(const std::string &host, content::WebContents *web_contents) override; private: std::map<std::string, CertPolicy> m_certPolicyforHost; diff --git a/src/core/net/system_network_context_manager.cpp b/src/core/net/system_network_context_manager.cpp index cf84b840b..1fba115c6 100644 --- a/src/core/net/system_network_context_manager.cpp +++ b/src/core/net/system_network_context_manager.cpp @@ -44,42 +44,23 @@ #include "net/system_network_context_manager.h" -#include <set> -#include <unordered_map> -#include <utility> - #include "base/bind.h" #include "base/command_line.h" -#include "base/feature_list.h" -#include "base/logging.h" -#include "base/sequence_checker.h" -#include "base/strings/string_split.h" -#include "base/task/post_task.h" -#include "base/values.h" -#include "build/build_config.h" #include "chrome/browser/net/chrome_mojo_proxy_resolver_factory.h" #include "chrome/common/chrome_switches.h" #include "components/certificate_transparency/ct_known_logs.h" -#include "components/network_session_configurator/common/network_features.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/cors_exempt_headers.h" +#include "components/network_session_configurator/common/network_switches.h" #include "content/public/browser/network_service_instance.h" -#include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" #include "content/public/common/service_names.mojom.h" -#include "content/public/common/user_agent.h" -#include "mojo/public/cpp/bindings/associated_interface_ptr.h" -#include "net/dns/public/util.h" #include "net/net_buildflags.h" -#include "net/third_party/uri_template/uri_template.h" #include "services/network/network_service.h" -#include "services/network/public/cpp/cross_thread_shared_url_loader_factory_info.h" +#include "services/network/public/cpp/cross_thread_pending_shared_url_loader_factory.h" #include "services/network/public/cpp/features.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/mojom/host_resolver.mojom.h" +#include "services/network/public/mojom/url_loader_factory.mojom.h" #include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h" -#include "url/gurl.h" namespace { @@ -100,8 +81,8 @@ network::mojom::HttpAuthDynamicParamsPtr CreateHttpAuthDynamicParams() network::mojom::HttpAuthDynamicParamsPtr auth_dynamic_params = network::mojom::HttpAuthDynamicParams::New(); auto *command_line = base::CommandLine::ForCurrentProcess(); - auth_dynamic_params->server_whitelist = command_line->GetSwitchValueASCII(switches::kAuthServerWhitelist); -// auth_dynamic_params->delegate_whitelist = command_line->GetSwitchValueASCII(switches::kAuthNegotiateDelegateWhitelist); + auth_dynamic_params->server_allowlist = command_line->GetSwitchValueASCII(switches::kAuthServerAllowlist); +// auth_dynamic_params->delegate_allowlist = command_line->GetSwitchValueASCII(switches::kAuthNegotiateDelegateWhitelist); // auth_dynamic_params->enable_negotiate_port = command_line->HasSwitch(switches::kEnableAuthNegotiatePort); return auth_dynamic_params; @@ -121,30 +102,34 @@ public: // mojom::URLLoaderFactory implementation: - void CreateLoaderAndStart(network::mojom::URLLoaderRequest request, int32_t routing_id, int32_t request_id, - uint32_t options, const network::ResourceRequest &url_request, - network::mojom::URLLoaderClientPtr client, + void CreateLoaderAndStart(mojo::PendingReceiver<network::mojom::URLLoader> receiver, + int32_t routing_id, + int32_t request_id, + uint32_t options, + const network::ResourceRequest &url_request, + mojo::PendingRemote<network::mojom::URLLoaderClient> client, const net::MutableNetworkTrafficAnnotationTag &traffic_annotation) override { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!manager_) return; - manager_->GetURLLoaderFactory()->CreateLoaderAndStart(std::move(request), routing_id, request_id, options, - url_request, std::move(client), traffic_annotation); + manager_->GetURLLoaderFactory()->CreateLoaderAndStart( + std::move(receiver), routing_id, request_id, options, url_request, + std::move(client), traffic_annotation); } - void Clone(network::mojom::URLLoaderFactoryRequest request) override + void Clone(mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) override { if (!manager_) return; - manager_->GetURLLoaderFactory()->Clone(std::move(request)); + manager_->GetURLLoaderFactory()->Clone(std::move(receiver)); } // SharedURLLoaderFactory implementation: - std::unique_ptr<network::SharedURLLoaderFactoryInfo> Clone() override + std::unique_ptr<network::PendingSharedURLLoaderFactory> Clone() override { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return std::make_unique<network::CrossThreadSharedURLLoaderFactoryInfo>(this); + return std::make_unique<network::CrossThreadPendingSharedURLLoaderFactory>(this); } void Shutdown() { manager_ = nullptr; } @@ -161,13 +146,8 @@ private: network::mojom::NetworkContext *SystemNetworkContextManager::GetContext() { - if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) { - // SetUp should already have been called. - DCHECK(io_thread_network_context_); - return io_thread_network_context_.get(); - } - - if (!network_service_network_context_ || network_service_network_context_.encountered_error()) { + if (!network_service_network_context_ || + !network_service_network_context_.is_connected()) { // This should call into OnNetworkServiceCreated(), which will re-create // the network service, if needed. There's a chance that it won't be // invoked, if the NetworkContext has encountered an error but the @@ -183,14 +163,14 @@ network::mojom::NetworkContext *SystemNetworkContextManager::GetContext() network::mojom::URLLoaderFactory *SystemNetworkContextManager::GetURLLoaderFactory() { // Create the URLLoaderFactory as needed. - if (url_loader_factory_ && !url_loader_factory_.encountered_error()) { + if (url_loader_factory_ && url_loader_factory_.is_connected()) { return url_loader_factory_.get(); } network::mojom::URLLoaderFactoryParamsPtr params = network::mojom::URLLoaderFactoryParams::New(); params->process_id = network::mojom::kBrowserProcessId; params->is_corb_enabled = false; - GetContext()->CreateURLLoaderFactory(mojo::MakeRequest(&url_loader_factory_), std::move(params)); + GetContext()->CreateURLLoaderFactory(url_loader_factory_.BindNewPipeAndPassReceiver(), std::move(params)); return url_loader_factory_.get(); } @@ -199,23 +179,6 @@ scoped_refptr<network::SharedURLLoaderFactory> SystemNetworkContextManager::GetS return shared_url_loader_factory_; } -void SystemNetworkContextManager::SetUp( - network::mojom::NetworkContextRequest *network_context_request, - network::mojom::NetworkContextParamsPtr *network_context_params, bool *stub_resolver_enabled, - base::Optional<std::vector<network::mojom::DnsOverHttpsServerPtr>> *dns_over_https_servers, - network::mojom::HttpAuthStaticParamsPtr *http_auth_static_params, - network::mojom::HttpAuthDynamicParamsPtr *http_auth_dynamic_params, bool *is_quic_allowed) -{ - if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) { - *network_context_request = mojo::MakeRequest(&io_thread_network_context_); - *network_context_params = CreateNetworkContextParams(); - } - *is_quic_allowed = false; - *http_auth_static_params = CreateHttpAuthStaticParams(); - *http_auth_dynamic_params = CreateHttpAuthDynamicParams(); - // GetStubResolverConfig(local_state_, stub_resolver_enabled, dns_over_https_servers); -} - // static SystemNetworkContextManager *SystemNetworkContextManager::CreateInstance() { @@ -249,17 +212,19 @@ SystemNetworkContextManager::~SystemNetworkContextManager() void SystemNetworkContextManager::OnNetworkServiceCreated(network::mojom::NetworkService *network_service) { - if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) - return; + bool is_quic_force_enabled = base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableQuic); // Disable QUIC globally - network_service->DisableQuic(); + if (!is_quic_force_enabled) + network_service->DisableQuic(); network_service->SetUpHttpAuth(CreateHttpAuthStaticParams()); network_service->ConfigureHttpAuthPrefs(CreateHttpAuthDynamicParams()); - // The system NetworkContext must be created first, since it sets - // |primary_network_context| to true. - network_service->CreateNetworkContext(MakeRequest(&network_service_network_context_), CreateNetworkContextParams()); + // The system NetworkContext is created first + network_service_network_context_.reset(); + network_service->CreateNetworkContext( + network_service_network_context_.BindNewPipeAndPassReceiver(), + CreateNetworkContextParams()); // Configure the stub resolver. This must be done after the system // NetworkContext is created, but before anything has the chance to use it. @@ -276,41 +241,21 @@ void SystemNetworkContextManager::AddSSLConfigToNetworkContextParams(network::mo network_context_params->initial_ssl_config->symantec_enforcement_disabled = true; } -network::mojom::NetworkContextParamsPtr SystemNetworkContextManager::CreateDefaultNetworkContextParams() +void SystemNetworkContextManager::ConfigureDefaultNetworkContextParams(network::mojom::NetworkContextParams *network_context_params) { - network::mojom::NetworkContextParamsPtr network_context_params = network::mojom::NetworkContextParams::New(); - content::UpdateCorsExemptHeader(network_context_params.get()); - network_context_params->enable_brotli = true; - // network_context_params->user_agent = GetUserAgent(); - // Disable referrers by default. Any consumer that enables referrers should // respect prefs::kEnableReferrers from the appropriate pref store. network_context_params->enable_referrers = false; - // const base::CommandLine& command_line = - // *base::CommandLine::ForCurrentProcess(); - - // // TODO(eroman): Figure out why this doesn't work in single-process mode, - // // or if it does work, now. - // // Should be possible now that a private isolate is used. - // // http://crbug.com/474654 - // if (!command_line.HasSwitch(switches::kWinHttpProxyResolver)) { - // if (command_line.HasSwitch(switches::kSingleProcess)) { - // LOG(ERROR) << "Cannot use V8 Proxy resolver in single process mode."; - // } else { network_context_params->proxy_resolver_factory = ChromeMojoProxyResolverFactory::CreateWithSelfOwnedReceiver(); - // } - // } - - // network_context_params->pac_quick_check_enabled = local_state_->GetBoolean(prefs::kQuickCheckEnabled); // Use the SystemNetworkContextManager to populate and update SSL // configuration. The SystemNetworkContextManager is owned by the // BrowserProcess itself, so will only be destroyed on shutdown, at which // point, all NetworkContexts will be destroyed as well. - AddSSLConfigToNetworkContextParams(network_context_params.get()); + AddSSLConfigToNetworkContextParams(network_context_params); // CT is only enabled on Desktop platforms for now. network_context_params->enforce_chrome_ct_policy = true; @@ -321,16 +266,13 @@ network::mojom::NetworkContextParamsPtr SystemNetworkContextManager::CreateDefau log_info->name = ct_log.log_name; network_context_params->ct_logs.push_back(std::move(log_info)); } - - network_context_params->http_09_on_non_default_ports_enabled = false; - - return network_context_params; } network::mojom::NetworkContextParamsPtr SystemNetworkContextManager::CreateNetworkContextParams() { // TODO(mmenke): Set up parameters here (in memory cookie store, etc). - network::mojom::NetworkContextParamsPtr network_context_params = CreateDefaultNetworkContextParams(); + network::mojom::NetworkContextParamsPtr network_context_params = network::mojom::NetworkContextParams::New(); + ConfigureDefaultNetworkContextParams(network_context_params.get()); network_context_params->context_name = std::string("system"); @@ -343,8 +285,6 @@ network::mojom::NetworkContextParamsPtr SystemNetworkContextManager::CreateNetwo network_context_params->enable_ftp_url_support = true; #endif - network_context_params->primary_network_context = true; - proxy_config_monitor_.AddToNetworkContextParams(network_context_params.get()); return network_context_params; diff --git a/src/core/net/system_network_context_manager.h b/src/core/net/system_network_context_manager.h index 288af5195..48cd99173 100644 --- a/src/core/net/system_network_context_manager.h +++ b/src/core/net/system_network_context_manager.h @@ -46,16 +46,10 @@ #define SYSTEM_NETWORK_CONTEXT_MANAGER_H_ #include <memory> -#include <string> -#include <vector> #include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/optional.h" -#include "services/network/public/mojom/host_resolver.mojom-forward.h" #include "services/network/public/mojom/network_context.mojom.h" #include "services/network/public/mojom/network_service.mojom-forward.h" -#include "services/network/public/mojom/ssl_config.mojom-forward.h" #include "services/network/public/mojom/url_loader_factory.mojom-forward.h" #include "net/proxy_config_monitor.h" @@ -67,10 +61,6 @@ class URLLoaderFactory; class SharedURLLoaderFactory; } // namespace network -namespace net_log { -class NetExportFileWriter; -} - // Responsible for creating and managing access to the system NetworkContext. // Lives on the UI thread. The NetworkContext this owns is intended for requests // not associated with a profile. It stores no data on disk, and has no HTTP @@ -105,27 +95,6 @@ public: // Destroys the global SystemNetworkContextManager instance. static void DeleteInstance(); - // If the network service is disabled, |network_context_request| will be for - // the NetworkContext used by the SystemNetworkContextManager and - // |network_context_params| as needed to set up a system NetworkContext. - // Otherwise, this method can still be used to help set up the IOThread's - // in-process URLRequestContext. - // - // Must be called before the system NetworkContext is first used. - // - // |stub_resolver_enabled|, |dns_over_https_servers|, - // |http_auth_static_params|, |http_auth_dynamic_params|, and - // |is_quic_allowed| are used to pass initial NetworkService state to the - // caller, so the NetworkService can be configured appropriately. Using - // NetworkService's Mojo interface to set those options would lead to races - // with other UI->IO thread network-related tasks, since Mojo doesn't preserve - // execution order relative to PostTasks. - void SetUp(network::mojom::NetworkContextRequest *network_context_request, - network::mojom::NetworkContextParamsPtr *network_context_params, bool *stub_resolver_enabled, - base::Optional<std::vector<network::mojom::DnsOverHttpsServerPtr>> *dns_over_https_servers, - network::mojom::HttpAuthStaticParamsPtr *http_auth_static_params, - network::mojom::HttpAuthDynamicParamsPtr *http_auth_dynamic_params, bool *is_quic_allowed); - // Returns the System NetworkContext. May only be called after SetUp(). Does // any initialization of the NetworkService that may be needed when first // called. @@ -151,8 +120,8 @@ public: // SSL configuration updates. void AddSSLConfigToNetworkContextParams(network::mojom::NetworkContextParams *network_context_params); - // Returns default set of parameters for configuring the network service. - network::mojom::NetworkContextParamsPtr CreateDefaultNetworkContextParams(); + // Configures the default set of parameters for the network context. + void ConfigureDefaultNetworkContextParams(network::mojom::NetworkContextParams *); private: class URLLoaderFactoryForSystem; @@ -167,17 +136,12 @@ private: // NetworkContext using the network service, if the network service is // enabled. nullptr, otherwise. - network::mojom::NetworkContextPtr network_service_network_context_; - - // This is a NetworkContext that wraps the IOThread's SystemURLRequestContext. - // Always initialized in SetUp, but it's only returned by Context() when the - // network service is disabled. - network::mojom::NetworkContextPtr io_thread_network_context_; + mojo::Remote<network::mojom::NetworkContext> network_service_network_context_; // URLLoaderFactory backed by the NetworkContext returned by GetContext(), so // consumers don't all need to create their own factory. scoped_refptr<URLLoaderFactoryForSystem> shared_url_loader_factory_; - network::mojom::URLLoaderFactoryPtr url_loader_factory_; + mojo::Remote<network::mojom::URLLoaderFactory> url_loader_factory_; ProxyConfigMonitor proxy_config_monitor_; diff --git a/src/core/net/url_request_context_getter_qt.cpp b/src/core/net/url_request_context_getter_qt.cpp deleted file mode 100644 index 6081a5e9f..000000000 --- a/src/core/net/url_request_context_getter_qt.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "url_request_context_getter_qt.h" -#include "profile_io_data_qt.h" - -#include "base/task/post_task.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" - -namespace QtWebEngineCore { - -URLRequestContextGetterQt::URLRequestContextGetterQt(ProfileIODataQt *data) - : m_profileIOData(data) -{ -} - -URLRequestContextGetterQt::~URLRequestContextGetterQt() -{ -} - -net::URLRequestContext *URLRequestContextGetterQt::GetURLRequestContext() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - return m_profileIOData->urlRequestContext(); -} - -scoped_refptr<base::SingleThreadTaskRunner> URLRequestContextGetterQt::GetNetworkTaskRunner() const -{ - return base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO}); -} - -} // namespace QtWebEngineCore diff --git a/src/core/net/url_request_context_getter_qt.h b/src/core/net/url_request_context_getter_qt.h deleted file mode 100644 index a6ef6eae0..000000000 --- a/src/core/net/url_request_context_getter_qt.h +++ /dev/null @@ -1,63 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef URL_REQUEST_CONTEXT_GETTER_QT_H -#define URL_REQUEST_CONTEXT_GETTER_QT_H - -#include "net/url_request/url_request_context_getter.h" - -namespace QtWebEngineCore { - -class ProfileIODataQt; - -class URLRequestContextGetterQt : public net::URLRequestContextGetter -{ -public: - URLRequestContextGetterQt(ProfileIODataQt *data); - net::URLRequestContext *GetURLRequestContext() override; - scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() const override; - -private: - virtual ~URLRequestContextGetterQt(); - ProfileIODataQt *m_profileIOData; -}; - -} // namespace QtWebEngineCore - -#endif // URL_REQUEST_CONTEXT_GETTER_QT_H diff --git a/src/core/net/url_request_custom_job.cpp b/src/core/net/url_request_custom_job.cpp deleted file mode 100644 index fe287d0b7..000000000 --- a/src/core/net/url_request_custom_job.cpp +++ /dev/null @@ -1,284 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "url_request_custom_job.h" -#include "url_request_custom_job_proxy.h" - -#include "api/qwebengineurlscheme.h" - -#include "base/strings/stringprintf.h" -#include "base/task/post_task.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" -#include "net/base/io_buffer.h" -#include "net/http/http_util.h" - -#include <QIODevice> - -using namespace net; - -namespace QtWebEngineCore { - -URLRequestCustomJob::URLRequestCustomJob(URLRequest *request, - NetworkDelegate *networkDelegate, - const std::string &scheme, - QPointer<ProfileAdapter> profileAdapter) - : URLRequestJob(request, networkDelegate) - , m_taskRunner(base::CreateSingleThreadTaskRunner({ content::BrowserThread::IO })) - , m_proxy(new URLRequestCustomJobProxy(this, scheme, profileAdapter)) - , m_pendingReadSize(0) - , m_pendingReadPos(0) - , m_pendingReadBuffer(nullptr) - , m_corsEnabled(QWebEngineUrlScheme::schemeByName(QByteArray::fromStdString(scheme)) - .flags().testFlag(QWebEngineUrlScheme::CorsEnabled)) -{ - m_device = nullptr; - m_error = 0; -} - -URLRequestCustomJob::~URLRequestCustomJob() -{ - m_proxy->m_client = nullptr; - if (m_device && m_device->isOpen()) - m_device->close(); - m_device = nullptr; - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&URLRequestCustomJobProxy::release, m_proxy)); -} - -void URLRequestCustomJob::Start() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - HttpRequestHeaders requestHeaders = request()->extra_request_headers(); - std::map<std::string, std::string> headers; - net::HttpRequestHeaders::Iterator it(requestHeaders); - while (it.GetNext()) - headers.emplace(it.name(), it.value()); - if (!request()->referrer().empty()) - headers.emplace("Referer", request()->referrer()); - - // TODO: handle UploadDataStream, for instance using a QIODevice wrapper. - - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&URLRequestCustomJobProxy::initialize, - m_proxy, - request()->url(), - request()->method(), - request()->initiator(), - std::move(headers))); -} - -void URLRequestCustomJob::Kill() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - m_proxy->m_client = nullptr; - if (m_device && m_device->isOpen()) - m_device->close(); - if (m_pendingReadBuffer) { - m_pendingReadBuffer->Release(); - m_pendingReadBuffer = nullptr; - m_pendingReadSize = 0; - m_pendingReadPos = 0; - } - m_device = nullptr; - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&URLRequestCustomJobProxy::release, - m_proxy)); - URLRequestJob::Kill(); -} - -bool URLRequestCustomJob::GetMimeType(std::string *mimeType) const -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (m_mimeType.size() > 0) { - *mimeType = m_mimeType; - return true; - } - return false; -} - -bool URLRequestCustomJob::GetCharset(std::string *charset) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (m_charset.size() > 0) { - *charset = m_charset; - return true; - } - return false; -} - -void URLRequestCustomJob::GetResponseInfo(HttpResponseInfo *info) -{ - // Based on net::URLRequestRedirectJob::StartAsync() - - if (m_error) - return; - - std::string headers; - if (m_redirect.is_valid()) { - headers += "HTTP/1.1 303 See Other\n"; - headers += base::StringPrintf("Location: %s\n", m_redirect.spec().c_str()); - } else { - headers += base::StringPrintf("HTTP/1.1 %i OK\n", 200); - if (m_mimeType.size() > 0) { - headers += base::StringPrintf("Content-Type: %s", m_mimeType.c_str()); - if (m_charset.size() > 0) - headers += base::StringPrintf("; charset=%s", m_charset.c_str()); - headers += "\n"; - } - } - if (m_corsEnabled) { - std::string origin; - if (request_->extra_request_headers().GetHeader("Origin", &origin)) { - headers += base::StringPrintf("Access-Control-Allow-Origin: %s\n", origin.c_str()); - headers += "Access-Control-Allow-Credentials: true\n"; - } - } - - info->headers = new HttpResponseHeaders(HttpUtil::AssembleRawHeaders(headers)); -} - -bool URLRequestCustomJob::IsRedirectResponse(GURL *location, int *http_status_code, bool * /*insecure_scheme_was_upgraded*/) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (m_redirect.is_valid()) { - *location = m_redirect; - *http_status_code = 303; - return true; - } - return false; -} - -int URLRequestCustomJob::ReadRawData(IOBuffer *buf, int bufSize) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (m_error) - return m_error; - qint64 rv = m_device ? m_device->read(buf->data(), bufSize) : -1; - if (rv > 0) { - return static_cast<int>(rv); - } else if (rv == 0) { - // Returning zero is interpreted as EOF by Chromium, so only - // return zero if we are the end of the file. - if (m_device->atEnd()) - return 0; - // Otherwise return IO_PENDING and call ReadRawDataComplete when we have data - // for them. - buf->AddRef(); - m_pendingReadPos = 0; - m_pendingReadSize = bufSize; - m_pendingReadBuffer = buf; - return ERR_IO_PENDING; - } else { - // QIODevice::read might have called fail on us. - if (m_error) - return m_error; - if (m_device && m_device->atEnd()) - return 0; - return ERR_FAILED; - } -} - -void URLRequestCustomJob::notifyExpectedContentSize(qint64 size) -{ - set_expected_content_size(size); -} - -void URLRequestCustomJob::notifyHeadersComplete() -{ - NotifyHeadersComplete(); -} - -void URLRequestCustomJob::notifyCanceled() -{ - NotifyCanceled(); -} - -void URLRequestCustomJob::notifyAborted() -{ - NotifyStartError(URLRequestStatus(URLRequestStatus::CANCELED, net::ERR_ABORTED)); -} - -void URLRequestCustomJob::notifyStartFailure(int error) -{ - NotifyStartError(URLRequestStatus::FromError(error)); -} - -void URLRequestCustomJob::notifyReadyRead() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (!m_device) - return; - if (!m_pendingReadSize) - return; - Q_ASSERT(m_pendingReadBuffer); - if (!m_pendingReadBuffer) - return; - - qint64 rv = m_device->read(m_pendingReadBuffer->data() + m_pendingReadPos, m_pendingReadSize - m_pendingReadPos); - if (rv == 0) - return; - if (rv < 0) { - if (m_error) - rv = m_error; - else if (m_device->atEnd()) - rv = 0; - else - rv = ERR_FAILED; - } else { - m_pendingReadPos += rv; - if (m_pendingReadPos < m_pendingReadSize && !m_device->atEnd()) - return; - rv = m_pendingReadPos; - } - // killJob may be called from ReadRawDataComplete - net::IOBuffer *buf = m_pendingReadBuffer; - m_pendingReadBuffer = nullptr; - m_pendingReadSize = 0; - m_pendingReadPos = 0; - ReadRawDataComplete(rv); - buf->Release(); -} - -base::TaskRunner *URLRequestCustomJob::taskRunner() -{ - return m_taskRunner.get(); -} - -} // namespace diff --git a/src/core/net/url_request_custom_job.h b/src/core/net/url_request_custom_job.h deleted file mode 100644 index 071a0a84f..000000000 --- a/src/core/net/url_request_custom_job.h +++ /dev/null @@ -1,101 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef URL_REQUEST_CUSTOM_JOB_H_ -#define URL_REQUEST_CUSTOM_JOB_H_ - -#include "net/url_request/url_request_job.h" -#include "url/gurl.h" - -#include "url_request_custom_job_proxy.h" - -#include <QtCore/QPointer> - -QT_FORWARD_DECLARE_CLASS(QIODevice) - -namespace QtWebEngineCore { - -class ProfileAdapter; -class URLRequestCustomJobDelegate; -class URLRequestCustomJobProxy; - -// A request job that handles reading custom URL schemes -class URLRequestCustomJob : public net::URLRequestJob, private URLRequestCustomJobProxy::Client -{ -public: - URLRequestCustomJob(net::URLRequest *request, - net::NetworkDelegate *networkDelegate, - const std::string &scheme, - QPointer<ProfileAdapter> profileAdapter); - // net::URLRequestJob: - void Start() override; - void Kill() override; - int ReadRawData(net::IOBuffer *buf, int buf_size) override; - bool GetMimeType(std::string *mimeType) const override; - bool GetCharset(std::string *charset) override; - void GetResponseInfo(net::HttpResponseInfo *info) override; - bool IsRedirectResponse(GURL *location, int *http_status_code, bool *insecure_scheme_was_upgraded) override; - -protected: - virtual ~URLRequestCustomJob(); - -private: - // URLRequestCustomJobProxy::Client: - void notifyExpectedContentSize(qint64 size) override; - void notifyHeadersComplete() override; - void notifyCanceled() override; - void notifyAborted() override; - void notifyStartFailure(int error) override; - void notifyReadyRead() override; - base::TaskRunner *taskRunner() override; - - scoped_refptr<base::TaskRunner> m_taskRunner; - scoped_refptr<URLRequestCustomJobProxy> m_proxy; - int m_pendingReadSize; - int m_pendingReadPos; - net::IOBuffer *m_pendingReadBuffer; - const bool m_corsEnabled; - - friend class URLRequestCustomJobProxy; - - DISALLOW_COPY_AND_ASSIGN(URLRequestCustomJob); -}; -} // namespace QtWebEngineCore - -#endif // URL_REQUEST_CUSTOM_JOB_H_ diff --git a/src/core/net/url_request_custom_job_proxy.cpp b/src/core/net/url_request_custom_job_proxy.cpp index cd7e173ee..f734db645 100644 --- a/src/core/net/url_request_custom_job_proxy.cpp +++ b/src/core/net/url_request_custom_job_proxy.cpp @@ -96,9 +96,13 @@ void URLRequestCustomJobProxy::reply(std::string mimeType, QIODevice *device) if (m_client->m_device && !m_client->m_device->isReadable()) m_client->m_device->open(QIODevice::ReadOnly); - qint64 size = m_client->m_device ? m_client->m_device->size() : -1; - if (size > 0) - m_client->notifyExpectedContentSize(size); + if (m_client->m_firstBytePosition > 0) + m_client->m_device->seek(m_client->m_firstBytePosition); + + qint64 deviceSize = m_client->m_device ? m_client->m_device->size() : -1; + if (deviceSize > 0) + m_client->notifyExpectedContentSize(deviceSize); + if (m_client->m_device && m_client->m_device->isReadable()) { m_started = true; m_client->notifyHeadersComplete(); diff --git a/src/core/net/url_request_custom_job_proxy.h b/src/core/net/url_request_custom_job_proxy.h index 7091c8319..b14322f91 100644 --- a/src/core/net/url_request_custom_job_proxy.h +++ b/src/core/net/url_request_custom_job_proxy.h @@ -42,7 +42,7 @@ #include "base/memory/weak_ptr.h" #include "base/optional.h" -#include "base/task_runner.h" +#include "base/sequenced_task_runner.h" #include "url/gurl.h" #include "url/origin.h" #include <QtCore/QPointer> @@ -67,6 +67,7 @@ public: std::string m_charset; GURL m_redirect; QIODevice *m_device; + int64_t m_firstBytePosition; int m_error; virtual void notifyExpectedContentSize(qint64 size) = 0; virtual void notifyHeadersComplete() = 0; @@ -74,7 +75,7 @@ public: virtual void notifyAborted() = 0; virtual void notifyStartFailure(int) = 0; virtual void notifyReadyRead() = 0; - virtual base::TaskRunner *taskRunner() = 0; + virtual base::SequencedTaskRunner *taskRunner() = 0; }; URLRequestCustomJobProxy(Client *client, @@ -100,7 +101,7 @@ public: std::string m_scheme; URLRequestCustomJobDelegate *m_delegate; QPointer<ProfileAdapter> m_profileAdapter; - scoped_refptr<base::TaskRunner> m_ioTaskRunner; + scoped_refptr<base::SequencedTaskRunner> m_ioTaskRunner; }; } // namespace QtWebEngineCore diff --git a/src/core/net/url_request_notification.cpp b/src/core/net/url_request_notification.cpp deleted file mode 100644 index 74c56254e..000000000 --- a/src/core/net/url_request_notification.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "url_request_notification.h" - -#include "base/supports_user_data.h" -#include "base/task/post_task.h" -#include "content/browser/web_contents/web_contents_impl.h" -#include "content/public/browser/browser_thread.h" -#include "net/url_request/url_request.h" - -#include "api/qwebengineurlrequestinfo_p.h" -#include "profile_io_data_qt.h" -#include "type_conversion.h" -#include "web_contents_adapter_client.h" -#include "web_contents_view_qt.h" - -#include <QVariant> - -namespace QtWebEngineCore { - -// Calls cancel() when the URLRequest is destroyed. -class UserData : public base::SupportsUserData::Data -{ -public: - UserData(URLRequestNotification *ptr) : m_ptr(ptr) {} - ~UserData() { m_ptr->cancel(); } - static const char key[]; - -private: - URLRequestNotification *m_ptr; -}; - -const char UserData::key[] = "QtWebEngineCore::URLRequestNotification"; - -URLRequestNotification::URLRequestNotification(net::URLRequest *request, bool isMainFrameRequest, GURL *newUrl, - QWebEngineUrlRequestInfo &&requestInfo, - content::ResourceRequestInfo::WebContentsGetter webContentsGetter, - net::CompletionOnceCallback callback, QPointer<ProfileAdapter> adapter) - : m_request(request) - , m_isMainFrameRequest(isMainFrameRequest) - , m_newUrl(newUrl) - , m_originalUrl(requestInfo.requestUrl()) - , m_requestInfo(std::move(requestInfo)) - , m_webContentsGetter(webContentsGetter) - , m_callback(std::move(callback)) - , m_profileAdapter(adapter) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - m_request->SetUserData(UserData::key, std::make_unique<UserData>(this)); - - base::PostTaskWithTraits( - FROM_HERE, - {content::BrowserThread::UI}, - base::BindOnce(&URLRequestNotification::notify, base::Unretained(this))); -} - - -void URLRequestNotification::notify() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - // May run concurrently with cancel() so no peeking at m_request here. - - int result = net::OK; - content::WebContents *webContents = m_webContentsGetter.Run(); - - if (webContents) { - if (m_profileAdapter && m_profileAdapter->requestInterceptor()) { - QWebEngineUrlRequestInterceptor *interceptor = m_profileAdapter->requestInterceptor(); - if (!interceptor->property("deprecated").toBool()) - interceptor->interceptRequest(m_requestInfo); - } - - WebContentsAdapterClient *client = - WebContentsViewQt::from(static_cast<content::WebContentsImpl*>(webContents)->GetView())->client(); - - if (!m_requestInfo.changed()) { - client->interceptRequest(m_requestInfo); - } - - if (m_requestInfo.changed()) { - result = m_requestInfo.d_ptr->shouldBlockRequest ? net::ERR_BLOCKED_BY_CLIENT : net::OK; - // We handle the rest of the changes later when we are back in I/O thread - } - } - - // Run the callback on the IO thread. - base::PostTaskWithTraits( - FROM_HERE, - {content::BrowserThread::IO}, - base::BindOnce(&URLRequestNotification::complete, base::Unretained(this), result)); -} - -void URLRequestNotification::cancel() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - // May run concurrently with notify() but we only touch m_request here. - - m_request = nullptr; -} - -void URLRequestNotification::complete(int error) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - if (m_request) { - if (m_requestInfo.changed()) { - if (m_originalUrl != m_requestInfo.d_ptr->url) - *m_newUrl = toGurl(m_requestInfo.d_ptr->url); - - if (!m_requestInfo.d_ptr->extraHeaders.isEmpty()) { - auto end = m_requestInfo.d_ptr->extraHeaders.constEnd(); - for (auto header = m_requestInfo.d_ptr->extraHeaders.constBegin(); header != end; ++header) { - std::string h = header.key().toStdString(); - if (base::LowerCaseEqualsASCII(h, "referer")) { - m_request->SetReferrer(header.value().toStdString()); - } else { - m_request->SetExtraRequestHeaderByName(h, header.value().toStdString(), /* overwrite */ true); - } - } - } - } - - if (m_request->status().status() != net::URLRequestStatus::CANCELED) - std::move(m_callback).Run(error); - m_request->RemoveUserData(UserData::key); - } - - delete this; -} - -} diff --git a/src/core/net/webui_controller_factory_qt.cpp b/src/core/net/webui_controller_factory_qt.cpp index 8c045bb7b..b645a6d72 100644 --- a/src/core/net/webui_controller_factory_qt.cpp +++ b/src/core/net/webui_controller_factory_qt.cpp @@ -44,39 +44,37 @@ #include "webui_controller_factory_qt.h" +#include "build_config_qt.h" + #include "base/bind.h" -#include "base/location.h" -#include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "chrome/browser/accessibility/accessibility_ui.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/devtools_ui.h" +#include "chrome/browser/ui/webui/net_internals/net_internals_ui.h" #include "chrome/browser/ui/webui/quota_internals/quota_internals_ui.h" +#include "chrome/browser/ui/webui/user_actions/user_actions_ui.h" #include "chrome/common/url_constants.h" -#include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" -#include "content/public/common/content_client.h" #include "content/public/common/url_utils.h" #include "extensions/buildflags/buildflags.h" #include "media/media_buildflags.h" #include "ppapi/buildflags/buildflags.h" #include "printing/buildflags/buildflags.h" -#include "ui/web_dialogs/web_dialog_ui.h" #include "url/gurl.h" #if defined(OS_LINUX) || defined(OS_ANDROID) -#include "chrome/browser/ui/webui/sandbox_internals_ui.h" +#include "chrome/browser/ui/webui/sandbox/sandbox_internals_ui.h" +#endif + +#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) +#include "chrome/browser/ui/webui/media/webrtc_logs_ui.h" #endif // The Following WebUIs are disabled because they currently doesn't build // or doesn't work, but would be interesting for us if they did: // #include "chrome/browser/ui/webui/inspect_ui.h" -// #include "chrome/browser/ui/webui/user_actions/user_actions_ui.h" - -// #if BUILDFLAG(ENABLE_WEBRTC) -// #include "chrome/browser/ui/webui/media/webrtc_logs_ui.h" -// #endif // #if BUILDFLAG(ENABLE_PRINT_PREVIEW) // #include "chrome/browser/ui/webui/print_preview/print_preview_ui.h" @@ -119,6 +117,8 @@ std::unique_ptr<WebUIController> NewWebUI(WebUI *web_ui, const GURL & /*url*/) // with it. WebUIFactoryFunction GetWebUIFactoryFunction(WebUI *web_ui, Profile *profile, const GURL &url) { + Q_UNUSED(web_ui); + Q_UNUSED(profile); // This will get called a lot to check all URLs, so do a quick check of other // schemes to filter out most URLs. if (!content::HasWebUIScheme(url)) @@ -126,6 +126,9 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI *web_ui, Profile *profile, co // We must compare hosts only since some of the Web UIs append extra stuff // after the host name. + if (url.host() == chrome::kChromeUINetInternalsHost) + return &NewWebUI<NetInternalsUI>; + if (url.host() == chrome::kChromeUIQuotaInternalsHost) return &NewWebUI<QuotaInternalsUI>; @@ -137,8 +140,9 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI *web_ui, Profile *profile, co if (url.host() == chrome::kChromeUIAccessibilityHost) return &NewWebUI<AccessibilityUI>; -// if (url.host_piece() == chrome::kChromeUIUserActionsHost) -// return &NewWebUI<UserActionsUI>; + if (url.host_piece() == chrome::kChromeUIUserActionsHost) + return &NewWebUI<UserActionsUI>; + // if (url.host_piece() == chrome::kChromeUIInspectHost) // return &NewWebUI<InspectUI>; // @@ -150,20 +154,16 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI *web_ui, Profile *profile, co // if (url.host_piece() == chrome::kChromeUIExtensionsFrameHost) // return &NewWebUI<extensions::ExtensionsUI>; //#endif -//#if BUILDFLAG(ENABLE_PLUGINS) -// if (url.host_piece() == chrome::kChromeUIFlashHost) -// return &NewWebUI<FlashUI>; -//#endif //#if BUILDFLAG(ENABLE_PRINT_PREVIEW) // if (url.host_piece() == chrome::kChromeUIPrintHost && // !profile->GetPrefs()->GetBoolean(prefs::kPrintPreviewDisabled)) { // return &NewWebUI<PrintPreviewUI>; // } //#endif -//#if BUILDFLAG(ENABLE_WEBRTC) -// if (url.host_piece() == chrome::kChromeUIWebRtcLogsHost) -// return &NewWebUI<WebRtcLogsUI>; -//#endif +#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) + if (url.host_piece() == chrome::kChromeUIWebRtcLogsHost) + return &NewWebUI<WebRtcLogsUI>; +#endif #if defined(OS_LINUX) || defined(OS_ANDROID) if (url.host_piece() == chrome::kChromeUISandboxHost) return &NewWebUI<SandboxInternalsUI>; diff --git a/src/core/net/webui_controller_factory_qt.h b/src/core/net/webui_controller_factory_qt.h index 1cc76349b..6dfc612e1 100644 --- a/src/core/net/webui_controller_factory_qt.h +++ b/src/core/net/webui_controller_factory_qt.h @@ -42,16 +42,8 @@ #include "base/macros.h" #include "base/memory/singleton.h" -#include "components/favicon_base/favicon_callback.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_controller_factory.h" -#include "ui/base/layout.h" - -class Profile; - -namespace base { -class RefCountedMemory; -} namespace QtWebEngineCore { diff --git a/src/core/ozone/BUILD.gn b/src/core/ozone/BUILD.gn index b96d8a47a..a01728842 100644 --- a/src/core/ozone/BUILD.gn +++ b/src/core/ozone/BUILD.gn @@ -1,6 +1,7 @@ # Copyright 2016 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//ui/base/ui_features.gni") source_set("qt") { sources = [ @@ -19,7 +20,7 @@ source_set("qt") { defines = [ "OZONE_IMPLEMENTATION" ] - if (is_linux && !is_desktop_linux) { - deps += [ "//ui/events/ozone:events_ozone_evdev"] + if (use_xkbcommon && use_x11) { + libs = [ "xkbfile" ] } } diff --git a/src/core/ozone/gl_context_qt.cpp b/src/core/ozone/gl_context_qt.cpp index 9813a3256..0e7213a3a 100644 --- a/src/core/ozone/gl_context_qt.cpp +++ b/src/core/ozone/gl_context_qt.cpp @@ -51,15 +51,17 @@ #endif QT_BEGIN_NAMESPACE - +#if QT_CONFIG(opengl) Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context(); +#endif + GLContextHelper* GLContextHelper::contextHelper = 0; namespace { inline void *resourceForContext(const QByteArray &resource) { -#ifndef QT_NO_OPENGL +#if QT_CONFIG(opengl) QOpenGLContext *shareContext = qt_gl_global_share_context(); if (!shareContext) { qFatal("QWebEngine: OpenGL resource sharing is not set up in QtQuick. Please make sure to call QtWebEngine::initialize() in your main() function."); @@ -81,6 +83,15 @@ void GLContextHelper::initialize() { if (!contextHelper) contextHelper = new GLContextHelper; +#if QT_CONFIG(opengl) + if (QGuiApplication::platformName() == QLatin1String("offscreen")){ + contextHelper->m_robustness = false; + return; + } + + if (QOpenGLContext *context = qt_gl_global_share_context()) + contextHelper->m_robustness = context->format().testOption(QSurfaceFormat::ResetNotification); +#endif } void GLContextHelper::destroy() @@ -114,7 +125,8 @@ void* GLContextHelper::getEGLConfig() void* GLContextHelper::getGlXConfig() { - return resourceForContext(QByteArrayLiteral("glxconfig")); + QByteArray resource = QByteArrayLiteral("glxconfig"); + return resourceForContext(resource); } void* GLContextHelper::getEGLDisplay() @@ -144,7 +156,7 @@ void* GLContextHelper::getNativeDisplay() QFunctionPointer GLContextHelper::getGlXGetProcAddress() { QFunctionPointer get_proc_address = nullptr; -#ifndef QT_NO_OPENGL +#if QT_CONFIG(opengl) if (QOpenGLContext *context = qt_gl_global_share_context()) { get_proc_address = context->getProcAddress("glXGetProcAddress"); } @@ -155,7 +167,7 @@ QFunctionPointer GLContextHelper::getGlXGetProcAddress() QFunctionPointer GLContextHelper::getEglGetProcAddress() { QFunctionPointer get_proc_address = nullptr; -#ifndef QT_NO_OPENGL +#if QT_CONFIG(opengl) if (QOpenGLContext *context = qt_gl_global_share_context()) { get_proc_address = context->getProcAddress("eglGetProcAddress"); } @@ -165,15 +177,9 @@ QFunctionPointer GLContextHelper::getEglGetProcAddress() bool GLContextHelper::isCreateContextRobustnessSupported() { -#if QT_CONFIG(opengl) - if (QGuiApplication::platformName() == QLatin1String("offscreen")) - return false; - - if (QOpenGLContext *context = qt_gl_global_share_context()) - return context->format().testOption(QSurfaceFormat::ResetNotification); -#endif - return false; + return contextHelper->m_robustness; } + QT_END_NAMESPACE #if defined(OS_WIN) diff --git a/src/core/ozone/gl_context_qt.h b/src/core/ozone/gl_context_qt.h index 8559af313..cc4f6b0d1 100644 --- a/src/core/ozone/gl_context_qt.h +++ b/src/core/ozone/gl_context_qt.h @@ -70,6 +70,7 @@ private: Q_INVOKABLE bool initializeContextOnBrowserThread(gl::GLContext* context, gl::GLSurface* surface, gl::GLContextAttribs attribs); static GLContextHelper* contextHelper; + bool m_robustness = false; }; QT_END_NAMESPACE diff --git a/src/core/ozone/gl_ozone_egl_qt.cpp b/src/core/ozone/gl_ozone_egl_qt.cpp index 2fa86d79b..04b336990 100644 --- a/src/core/ozone/gl_ozone_egl_qt.cpp +++ b/src/core/ozone/gl_ozone_egl_qt.cpp @@ -38,13 +38,13 @@ ****************************************************************************/ #if defined(USE_OZONE) -#include "gl_ozone_egl_qt.h" +#include <QtCore/qobject.h> +#include <QtGui/qtgui-config.h> #include "gl_context_qt.h" +#include "gl_ozone_egl_qt.h" #include "gl_surface_egl_qt.h" #include "base/files/file_path.h" #include "base/native_library.h" -#include "gl_context_qt.h" -#include "gl_ozone_egl_qt.h" #include "ui/gl/gl_context_egl.h" #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_surface.h" @@ -55,15 +55,6 @@ #include <EGL/egl.h> #include <dlfcn.h> -#include <QtGui/qtgui-config.h> // for QT_NO_OPENGL - -#ifndef QT_NO_OPENGL -#include <QOpenGLContext> -QT_BEGIN_NAMESPACE -Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context(); -QT_END_NAMESPACE -#endif - namespace ui { base::NativeLibrary LoadLibrary(const base::FilePath& filename) { @@ -88,13 +79,11 @@ bool GLOzoneEGLQt::LoadGLES2Bindings(gl::GLImplementation /*implementation*/) reinterpret_cast<gl::GLGetProcAddressProc>( base::GetFunctionPointerFromNativeLibrary(eglgles2Library, "eglGetProcAddress")); -#ifndef QT_NO_OPENGL +#if QT_CONFIG(opengl) if (!get_proc_address) { // QTBUG-63341 most likely libgles2 not linked with libegl -> fallback to qpa - if (QOpenGLContext *context = qt_gl_global_share_context()) { - get_proc_address = reinterpret_cast<gl::GLGetProcAddressProc>( - context->getProcAddress("eglGetProcAddress")); - } + get_proc_address = + reinterpret_cast<gl::GLGetProcAddressProc>(GLContextHelper::getEglGetProcAddress()); } #endif @@ -142,14 +131,11 @@ scoped_refptr<gl::GLSurface> GLOzoneEGLQt::CreateOffscreenGLSurface(const gfx::S return nullptr; } -intptr_t GLOzoneEGLQt::GetNativeDisplay() +gl::EGLDisplayPlatform GLOzoneEGLQt::GetNativeDisplay() { static void *display = GLContextHelper::getNativeDisplay(); - - if (display) - return reinterpret_cast<intptr_t>(display); - - return reinterpret_cast<intptr_t>(EGL_DEFAULT_DISPLAY); + static gl::EGLDisplayPlatform platform(display ? reinterpret_cast<intptr_t>(display) : EGL_DEFAULT_DISPLAY); + return platform; } } // namespace ui diff --git a/src/core/ozone/gl_ozone_egl_qt.h b/src/core/ozone/gl_ozone_egl_qt.h index c24d03a81..c55ba232c 100644 --- a/src/core/ozone/gl_ozone_egl_qt.h +++ b/src/core/ozone/gl_ozone_egl_qt.h @@ -58,7 +58,7 @@ public: protected: // Returns native platform display handle. This is used to obtain the EGL // display connection for the native display. - intptr_t GetNativeDisplay() override; + gl::EGLDisplayPlatform GetNativeDisplay() override; // Sets up GL bindings for the native surface. bool LoadGLES2Bindings(gl::GLImplementation implementation) override; diff --git a/src/core/ozone/gl_ozone_glx_qt.cpp b/src/core/ozone/gl_ozone_glx_qt.cpp index f934a5c80..60b970209 100644 --- a/src/core/ozone/gl_ozone_glx_qt.cpp +++ b/src/core/ozone/gl_ozone_glx_qt.cpp @@ -95,11 +95,6 @@ bool GLOzoneGLXQt::InitializeStaticGLBindings( return true; } -void GLOzoneGLXQt::InitializeDebugGLBindings() { - gl::InitializeDebugGLBindingsGL(); - gl::InitializeDebugGLBindingsGLX(); -} - void GLOzoneGLXQt::SetDisabledExtensionsPlatform( const std::string& disabled_extensions) { gl::SetDisabledExtensionsGLX(disabled_extensions); diff --git a/src/core/ozone/gl_ozone_glx_qt.h b/src/core/ozone/gl_ozone_glx_qt.h index 1596ea12f..7825cba35 100644 --- a/src/core/ozone/gl_ozone_glx_qt.h +++ b/src/core/ozone/gl_ozone_glx_qt.h @@ -54,7 +54,6 @@ public: bool InitializeGLOneOffPlatform() override; bool InitializeStaticGLBindings(gl::GLImplementation implementation) override; - void InitializeDebugGLBindings() override; bool InitializeExtensionSettingsOneOffPlatform() override; void ShutdownGL() override; void SetDisabledExtensionsPlatform( diff --git a/src/core/ozone/gl_surface_egl_qt.cpp b/src/core/ozone/gl_surface_egl_qt.cpp index a6988bbf3..447826baa 100644 --- a/src/core/ozone/gl_surface_egl_qt.cpp +++ b/src/core/ozone/gl_surface_egl_qt.cpp @@ -44,7 +44,7 @@ #include "gl_context_qt.h" #include "ozone/gl_surface_egl_qt.h" -#if !defined(OS_MACOSX) +#if !defined(OS_MAC) #include "ui/gl/egl_util.h" #include "ui/gl/gl_surface_egl.h" #include "ui/gl/init/gl_factory.h" @@ -72,6 +72,9 @@ bool GLSurfaceEGLQt::InitializeOneOff() if (s_initialized) return true; + // Must be called before initializing the display. + g_driver_egl.InitializeClientExtensionBindings(); + g_display = GLContextHelper::getEGLDisplay(); if (!g_display) { LOG(ERROR) << "GLContextHelper::getEGLDisplay() failed."; @@ -90,7 +93,7 @@ bool GLSurfaceEGLQt::InitializeOneOff() } g_extensions = eglQueryString(g_display, EGL_EXTENSIONS); - g_egl_surfaceless_context_supported = ExtensionsContain(g_extensions, "EGL_KHR_surfaceless_context"); + g_egl_surfaceless_context_supported = ExtensionsContain(g_extensions.c_str(), "EGL_KHR_surfaceless_context"); if (g_egl_surfaceless_context_supported) { scoped_refptr<GLSurface> surface = new GLSurfacelessQtEGL(gfx::Size(1, 1)); gl::GLContextAttribs attribs; @@ -107,6 +110,10 @@ bool GLSurfaceEGLQt::InitializeOneOff() context->ReleaseCurrent(surface.get()); } } + + // Must be called after initializing the display. + g_driver_egl.InitializeExtensionBindings(); + s_initialized = true; return true; } @@ -174,21 +181,35 @@ bool GLSurfaceEGL::IsANGLEFeatureControlSupported() return false; } +bool GLSurfaceEGL::IsANGLEPowerPreferenceSupported() +{ + return false; +} + +bool GLSurfaceEGL::IsDisplaySemaphoreShareGroupSupported() +{ + return false; +} + +bool GLSurfaceEGL::IsRobustnessVideoMemoryPurgeSupported() +{ + return false; +} + void GLSurfaceEGL::ShutdownOneOff() { } const char* GLSurfaceEGL::GetEGLExtensions() { - return GLSurfaceQt::g_extensions; + return GLSurfaceQt::g_extensions.c_str(); } bool GLSurfaceEGL::HasEGLExtension(const char* name) { return ExtensionsContain(GetEGLExtensions(), name); } - -bool GLSurfaceEGL::InitializeOneOff(EGLNativeDisplayType /*native_display*/) +bool GLSurfaceEGL::InitializeOneOff(gl::EGLDisplayPlatform /*native_display*/) { return GLSurfaceEGLQt::InitializeOneOff(); } @@ -245,7 +266,7 @@ void GLSurfaceEGLQt::Destroy() } bool GLSurfaceEGLQt::Resize(const gfx::Size& size, float scale_factor, - ColorSpace color_space, bool has_alpha) + const gfx::ColorSpace &color_space, bool has_alpha) { if (size == m_size) return true; @@ -296,7 +317,7 @@ bool GLSurfacelessQtEGL::IsSurfaceless() const } bool GLSurfacelessQtEGL::Resize(const gfx::Size& size, float scale_factor, - ColorSpace color_space, bool has_alpha) + const gfx::ColorSpace &color_space, bool has_alpha) { m_size = size; return true; @@ -334,4 +355,4 @@ std::string DriverEGL::GetPlatformExtensions() return ""; } } // namespace gl -#endif // !defined(OS_MACOSX) +#endif // !defined(OS_MAC) diff --git a/src/core/ozone/gl_surface_egl_qt.h b/src/core/ozone/gl_surface_egl_qt.h index ecc2327b3..dff25e433 100644 --- a/src/core/ozone/gl_surface_egl_qt.h +++ b/src/core/ozone/gl_surface_egl_qt.h @@ -57,7 +57,8 @@ public: void Destroy() override; void* GetHandle() override; bool Resize(const gfx::Size& size, float scale_factor, - ColorSpace color_space, bool has_alpha) override; + const gfx::ColorSpace &color_space, bool has_alpha) override; + protected: ~GLSurfaceEGLQt(); @@ -85,7 +86,7 @@ public: void Destroy() override; bool IsSurfaceless() const override; bool Resize(const gfx::Size& size, float scale_factor, - ColorSpace color_space, bool has_alpha) override; + const gfx::ColorSpace &color_space, bool has_alpha) override; EGLSurface GetHandle() override; void* GetShareHandle() override; diff --git a/src/core/ozone/gl_surface_glx_qt.cpp b/src/core/ozone/gl_surface_glx_qt.cpp index e150c940a..c796444b1 100644 --- a/src/core/ozone/gl_surface_glx_qt.cpp +++ b/src/core/ozone/gl_surface_glx_qt.cpp @@ -45,8 +45,7 @@ #include "ozone/gl_surface_glx_qt.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_surface_glx.h" -#include <GL/glx.h> -#include <GL/glxext.h> +#include "ui/gfx/x/x11_types.h" namespace gl { @@ -63,7 +62,7 @@ void GLSurfaceGLX::ShutdownOneOff() bool GLSurfaceGLX::IsCreateContextSupported() { - return ExtensionsContain(GLSurfaceQt::g_extensions, "GLX_ARB_create_context"); + return HasGLXExtension("GLX_ARB_create_context"); } bool GLSurfaceGLX::IsCreateContextRobustnessSupported() @@ -88,7 +87,7 @@ bool GLSurfaceGLX::IsCreateContextProfileSupported() bool GLSurfaceGLX::IsCreateContextES2ProfileSupported() { - return ExtensionsContain(GLSurfaceQt::g_extensions, "GLX_ARB_create_context_es2_profile"); + return HasGLXExtension("GLX_ARB_create_context_es2_profile"); } bool GLSurfaceGLX::IsOMLSyncControlSupported() @@ -98,17 +97,22 @@ bool GLSurfaceGLX::IsOMLSyncControlSupported() bool GLSurfaceGLX::HasGLXExtension(const char *name) { - return ExtensionsContain(GLSurfaceQt::g_extensions, name); + return ExtensionsContain(GLSurfaceQt::g_extensions.c_str(), name); } bool GLSurfaceGLX::IsTextureFromPixmapSupported() { - return ExtensionsContain(GLSurfaceQt::g_extensions, "GLX_EXT_texture_from_pixmap"); + return HasGLXExtension("GLX_EXT_texture_from_pixmap"); +} + +bool GLSurfaceGLX::IsRobustnessVideoMemoryPurgeSupported() +{ + return false; } const char* GLSurfaceGLX::GetGLXExtensions() { - return GLSurfaceQt::g_extensions; + return GLSurfaceQt::g_extensions.c_str(); } bool GLSurfaceGLXQt::InitializeOneOff() @@ -154,7 +158,7 @@ bool GLSurfaceGLXQt::InitializeExtensionSettingsOneOff() Display* display = static_cast<Display*>(g_display); GLSurfaceQt::g_extensions = glXQueryExtensionsString(display, 0); - g_driver_glx.InitializeExtensionBindings(g_extensions); + g_driver_glx.InitializeExtensionBindings(g_extensions.c_str()); return true; } @@ -171,9 +175,9 @@ bool GLSurfaceGLXQt::Initialize(GLSurfaceFormat format) const int pbuffer_attributes[] = { GLX_PBUFFER_WIDTH, m_size.width(), GLX_PBUFFER_HEIGHT, m_size.height(), - GLX_LARGEST_PBUFFER, x11::False, - GLX_PRESERVED_CONTENTS, x11::False, - x11::None // MEMO doc: ...must be terminated with None or NULL + GLX_LARGEST_PBUFFER, GL_FALSE, + GLX_PRESERVED_CONTENTS, GL_FALSE, + GL_NONE // MEMO doc: ...must be terminated with None or NULL }; m_surfaceBuffer = glXCreatePbuffer(display, static_cast<GLXFBConfig>(g_config), pbuffer_attributes); diff --git a/src/core/ozone/gl_surface_glx_qt.h b/src/core/ozone/gl_surface_glx_qt.h index 3a465f448..e894423b7 100644 --- a/src/core/ozone/gl_surface_glx_qt.h +++ b/src/core/ozone/gl_surface_glx_qt.h @@ -42,9 +42,7 @@ #include "gl_surface_qt.h" -extern "C" { -#include <X11/Xlib.h> -} +#include "ui/gfx/x/x11_types.h" namespace gl { diff --git a/src/core/ozone/gl_surface_qt.cpp b/src/core/ozone/gl_surface_qt.cpp index e9da5e6a5..990a62f8b 100644 --- a/src/core/ozone/gl_surface_qt.cpp +++ b/src/core/ozone/gl_surface_qt.cpp @@ -43,7 +43,7 @@ #include "gl_surface_qt.h" -#if !defined(OS_MACOSX) +#if !defined(OS_MAC) #include <QGuiApplication> #include "gl_context_qt.h" @@ -76,9 +76,9 @@ namespace { bool g_initializedEGL = false; } -void* GLSurfaceQt::g_display = NULL; -void* GLSurfaceQt::g_config = NULL; -const char* GLSurfaceQt::g_extensions = NULL; +void* GLSurfaceQt::g_display = nullptr; +void* GLSurfaceQt::g_config = nullptr; +std::string GLSurfaceQt::g_extensions; GLSurfaceQt::~GLSurfaceQt() { @@ -99,7 +99,7 @@ GLSurfaceQt::GLSurfaceQt(const gfx::Size& size) bool GLSurfaceQt::HasEGLExtension(const char* name) { - return ExtensionsContain(g_extensions, name); + return ExtensionsContain(g_extensions.c_str(), name); } bool GLSurfaceQt::IsOffscreen() @@ -196,14 +196,14 @@ CreateOffscreenGLSurfaceWithFormat(const gfx::Size& size, GLSurfaceFormat format } LOG(ERROR) << "Requested OpenGL implementation is not supported. Implementation: " << GetGLImplementation(); Q_UNREACHABLE(); - return NULL; + return nullptr; } scoped_refptr<GLSurface> CreateViewGLSurface(gfx::AcceleratedWidget window) { QT_NOT_USED - return NULL; + return nullptr; } } // namespace init @@ -238,6 +238,26 @@ bool DirectCompositionSurfaceWin::IsHDRSupported() { return false; } + +bool DirectCompositionSurfaceWin::IsSwapChainTearingSupported() +{ + return false; +} + +bool DirectCompositionSurfaceWin::AreOverlaysSupported() +{ + return false; +} + +UINT DirectCompositionSurfaceWin::GetOverlaySupportFlags(DXGI_FORMAT format) +{ + Q_UNUSED(format); + return 0; +} + +void DirectCompositionSurfaceWin::DisableDecodeSwapChain() +{ +} } // namespace gl #endif -#endif // !defined(OS_MACOSX) +#endif // !defined(OS_MAC) diff --git a/src/core/ozone/gl_surface_qt.h b/src/core/ozone/gl_surface_qt.h index cbdc8876a..b3a53d6b3 100644 --- a/src/core/ozone/gl_surface_qt.h +++ b/src/core/ozone/gl_surface_qt.h @@ -37,11 +37,11 @@ ** ****************************************************************************/ - - #ifndef GL_SURFACE_QT_H_ #define GL_SURFACE_QT_H_ +#include <string> + #include "ui/gfx/geometry/size.h" #include "ui/gl/gl_surface.h" @@ -71,7 +71,7 @@ protected: public: static void* g_config; static void* g_display; - static const char* g_extensions; + static std::string g_extensions; private: DISALLOW_COPY_AND_ASSIGN(GLSurfaceQt); diff --git a/src/core/ozone/ozone_platform_qt.cpp b/src/core/ozone/ozone_platform_qt.cpp index 2ab274b8f..1d6fa1ed5 100644 --- a/src/core/ozone/ozone_platform_qt.cpp +++ b/src/core/ozone/ozone_platform_qt.cpp @@ -40,22 +40,35 @@ #include "ozone_platform_qt.h" #if defined(USE_OZONE) +#include "ui/base/buildflags.h" +#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h" #include "ui/base/ime/input_method.h" #include "ui/display/types/native_display_delegate.h" +#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h" +#include "ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h" #include "ui/ozone/common/stub_client_native_pixmap_factory.h" #include "ui/ozone/common/stub_overlay_manager.h" -#include "ui/ozone/public/cursor_factory_ozone.h" #include "ui/ozone/public/gpu_platform_support_host.h" #include "ui/ozone/public/input_controller.h" #include "ui/ozone/public/ozone_platform.h" +#include "ui/ozone/public/platform_screen.h" #include "ui/ozone/public/system_input_injector.h" #include "ui/platform_window/platform_window_delegate.h" #include "ui/platform_window/platform_window_init_properties.h" -#include "ui/platform_window/platform_window.h" #include "surface_factory_qt.h" #include "platform_window_qt.h" +#if BUILDFLAG(USE_XKBCOMMON) && defined(USE_X11) +#include "ui/events/ozone/layout/xkb/xkb_evdev_codes.h" +#include "ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.h" + +#include <X11/XKBlib.h> +#include <X11/extensions/XKBrules.h> + +extern void *GetQtXDisplay(); +#endif // BUILDFLAG(USE_XKBCOMMON) && defined(USE_X11) + namespace ui { namespace { @@ -66,26 +79,31 @@ public: ~OzonePlatformQt() override; ui::SurfaceFactoryOzone* GetSurfaceFactoryOzone() override; - ui::CursorFactoryOzone* GetCursorFactoryOzone() override; + ui::CursorFactory* GetCursorFactory() override; GpuPlatformSupportHost* GetGpuPlatformSupportHost() override; std::unique_ptr<PlatformWindow> CreatePlatformWindow(PlatformWindowDelegate* delegate, PlatformWindowInitProperties properties) override; std::unique_ptr<display::NativeDisplayDelegate> CreateNativeDisplayDelegate() override; ui::InputController* GetInputController() override; std::unique_ptr<ui::SystemInputInjector> CreateSystemInputInjector() override; ui::OverlayManagerOzone* GetOverlayManager() override; - std::unique_ptr<InputMethod> CreateInputMethod(internal::InputMethodDelegate *delegate) override; - + std::unique_ptr<InputMethod> CreateInputMethod(internal::InputMethodDelegate *delegate, gfx::AcceleratedWidget widget) override; + std::unique_ptr<ui::PlatformScreen> CreateScreen() override { return nullptr; } private: void InitializeUI(const ui::OzonePlatform::InitParams &) override; void InitializeGPU(const ui::OzonePlatform::InitParams &) override; std::unique_ptr<QtWebEngineCore::SurfaceFactoryQt> surface_factory_ozone_; - std::unique_ptr<CursorFactoryOzone> cursor_factory_ozone_; + std::unique_ptr<CursorFactory> cursor_factory_ozone_; std::unique_ptr<GpuPlatformSupportHost> gpu_platform_support_host_; std::unique_ptr<InputController> input_controller_; std::unique_ptr<OverlayManagerOzone> overlay_manager_; +#if BUILDFLAG(USE_XKBCOMMON) && defined(USE_X11) + XkbEvdevCodes m_xkbEvdevCodeConverter; +#endif + std::unique_ptr<KeyboardLayoutEngine> m_keyboardLayoutEngine; + DISALLOW_COPY_AND_ASSIGN(OzonePlatformQt); }; @@ -99,7 +117,7 @@ ui::SurfaceFactoryOzone* OzonePlatformQt::GetSurfaceFactoryOzone() return surface_factory_ozone_.get(); } -ui::CursorFactoryOzone* OzonePlatformQt::GetCursorFactoryOzone() +ui::CursorFactory* OzonePlatformQt::GetCursorFactory() { return cursor_factory_ozone_.get(); } @@ -135,12 +153,75 @@ std::unique_ptr<display::NativeDisplayDelegate> OzonePlatformQt::CreateNativeDis return nullptr; } +#if BUILDFLAG(USE_XKBCOMMON) && defined(USE_X11) +static std::string getCurrentKeyboardLayout() +{ + Display *dpy = static_cast<Display *>(GetQtXDisplay()); + if (dpy == nullptr) + return std::string(); + + XkbStateRec state; + if (XkbGetState(dpy, XkbUseCoreKbd, &state) != 0) + return std::string(); + + XkbRF_VarDefsRec vdr {}; // zero initialize it + struct Cleanup { + XkbRF_VarDefsRec &vdr; + Cleanup(XkbRF_VarDefsRec &vdr) : vdr(vdr) { } + ~Cleanup() { + free (vdr.model); + free (vdr.layout); + free (vdr.variant); + free (vdr.options); + } + } cleanup(vdr); + if (XkbRF_GetNamesProp(dpy, nullptr, &vdr) == 0) + return std::string(); + + char *layout = strtok(vdr.layout, ","); + for (int i = 0; i < state.group; i++) { + layout = strtok(nullptr, ","); + if (layout == nullptr) + return std::string(); + } + + char *variant = strtok(vdr.variant, ","); + if (!variant) + return layout; + + for (int i = 0; i < state.group; i++) { + variant = strtok(nullptr, ","); + if (variant == nullptr) + return layout; + } + + std::string layoutWithVariant = layout; + layoutWithVariant = layoutWithVariant.append("-"); + layoutWithVariant = layoutWithVariant.append(variant); + return layoutWithVariant; +} +#endif // BUILDFLAG(USE_XKBCOMMON) && defined(USE_X11) + void OzonePlatformQt::InitializeUI(const ui::OzonePlatform::InitParams &) { overlay_manager_.reset(new StubOverlayManager()); - cursor_factory_ozone_.reset(new CursorFactoryOzone()); + cursor_factory_ozone_.reset(new BitmapCursorFactoryOzone()); gpu_platform_support_host_.reset(ui::CreateStubGpuPlatformSupportHost()); input_controller_ = CreateStubInputController(); + +#if BUILDFLAG(USE_XKBCOMMON) && defined(USE_X11) + std::string layout = getCurrentKeyboardLayout(); + if (layout.empty()) { + m_keyboardLayoutEngine = std::make_unique<StubKeyboardLayoutEngine>(); + } else { + m_keyboardLayoutEngine = std::make_unique<XkbKeyboardLayoutEngine>(m_xkbEvdevCodeConverter); + m_keyboardLayoutEngine->SetCurrentLayoutByName(layout); + } +#else + m_keyboardLayoutEngine = std::make_unique<StubKeyboardLayoutEngine>(); +#endif // BUILDFLAG(USE_XKBCOMMON) && defined(USE_X11) + + KeyboardLayoutEngineManager::SetKeyboardLayoutEngine(m_keyboardLayoutEngine.get()); } void OzonePlatformQt::InitializeGPU(const ui::OzonePlatform::InitParams &) @@ -148,7 +229,7 @@ void OzonePlatformQt::InitializeGPU(const ui::OzonePlatform::InitParams &) surface_factory_ozone_.reset(new QtWebEngineCore::SurfaceFactoryQt()); } -std::unique_ptr<InputMethod> OzonePlatformQt::CreateInputMethod(internal::InputMethodDelegate *) +std::unique_ptr<InputMethod> OzonePlatformQt::CreateInputMethod(internal::InputMethodDelegate *, gfx::AcceleratedWidget) { NOTREACHED(); return nullptr; diff --git a/src/core/ozone/platform_window_qt.h b/src/core/ozone/platform_window_qt.h index ca4a00313..b1021df9d 100644 --- a/src/core/ozone/platform_window_qt.h +++ b/src/core/ozone/platform_window_qt.h @@ -46,11 +46,10 @@ #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/rect.h" #include "ui/platform_window/platform_window.h" +#include "ui/platform_window/platform_window_delegate.h" namespace ui { -class PlatformWindowDelegate; - class PlatformWindowQt : public PlatformWindow, public PlatformEventDispatcher { public: @@ -59,9 +58,10 @@ public: // PlatformWindow: gfx::Rect GetBounds() override; void SetBounds(const gfx::Rect& bounds) override; - void Show() override { } + void Show(bool inactive = false) override { } void Hide() override { } void Close() override { } + bool IsVisible() const { return true; } void SetTitle(const base::string16&) override { } void SetCapture() override { } void ReleaseCapture() override { } @@ -78,6 +78,11 @@ public: gfx::Rect GetRestoredBoundsInPixels() const override { return gfx::Rect(); } void Activate() override { } void Deactivate() override { } + void SetUseNativeFrame(bool use_native_frame) override { } + bool ShouldUseNativeFrame() const override { return false; } + void SetWindowIcons(const gfx::ImageSkia& window_icon, + const gfx::ImageSkia& app_icon) override { } + void SizeConstraintsChanged() override { } // PlatformEventDispatcher: bool CanDispatchEvent(const PlatformEvent& event) override; diff --git a/src/core/ozone/surface_factory_qt.cpp b/src/core/ozone/surface_factory_qt.cpp index 5420b4809..12b997148 100644 --- a/src/core/ozone/surface_factory_qt.cpp +++ b/src/core/ozone/surface_factory_qt.cpp @@ -37,26 +37,19 @@ ** ****************************************************************************/ +#if defined(USE_OZONE) #include "surface_factory_qt.h" -#include "gl_context_qt.h" -#include "gl_ozone_egl_qt.h" + +#include "ozone/gl_context_qt.h" +#include "ozone/gl_ozone_egl_qt.h" #if defined(USE_GLX) -#include "gl_ozone_glx_qt.h" +#include "ozone/gl_ozone_glx_qt.h" #endif -#include "ui/gl/gl_surface.h" -#include <QGuiApplication> - -#if defined(USE_OZONE) - -#include "ozone/gl_ozone_egl_qt.h" -#include "ozone/surface_factory_qt.h" -#include "ui/gl/gl_surface.h" namespace QtWebEngineCore { SurfaceFactoryQt::SurfaceFactoryQt() { - Q_ASSERT(qApp); #if defined(USE_GLX) if (GLContextHelper::getGlXConfig()) { m_impl = gl::kGLImplementationDesktopGL; diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp index 9e8687a47..40090f8ec 100644 --- a/src/core/permission_manager_qt.cpp +++ b/src/core/permission_manager_qt.cpp @@ -52,7 +52,7 @@ namespace QtWebEngineCore { -ProfileAdapter::PermissionType toQt(content::PermissionType type) +static ProfileAdapter::PermissionType toQt(content::PermissionType type) { switch (type) { case content::PermissionType::GEOLOCATION: @@ -61,12 +61,15 @@ ProfileAdapter::PermissionType toQt(content::PermissionType type) return ProfileAdapter::AudioCapturePermission; case content::PermissionType::VIDEO_CAPTURE: return ProfileAdapter::VideoCapturePermission; - case content::PermissionType::CLIPBOARD_READ: + case content::PermissionType::CLIPBOARD_READ_WRITE: return ProfileAdapter::ClipboardRead; - case content::PermissionType::CLIPBOARD_WRITE: + case content::PermissionType::CLIPBOARD_SANITIZED_WRITE: return ProfileAdapter::ClipboardWrite; case content::PermissionType::NOTIFICATIONS: return ProfileAdapter::NotificationPermission; + case content::PermissionType::ACCESSIBILITY_EVENTS: + case content::PermissionType::CAMERA_PAN_TILT_ZOOM: + return ProfileAdapter::UnsupportedPermission; case content::PermissionType::FLASH: case content::PermissionType::MIDI_SYSEX: case content::PermissionType::PROTECTED_MEDIA_IDENTIFIER: @@ -74,23 +77,51 @@ ProfileAdapter::PermissionType toQt(content::PermissionType type) case content::PermissionType::DURABLE_STORAGE: case content::PermissionType::BACKGROUND_SYNC: case content::PermissionType::SENSORS: - case content::PermissionType::ACCESSIBILITY_EVENTS: case content::PermissionType::PAYMENT_HANDLER: case content::PermissionType::BACKGROUND_FETCH: case content::PermissionType::IDLE_DETECTION: case content::PermissionType::PERIODIC_BACKGROUND_SYNC: case content::PermissionType::WAKE_LOCK_SCREEN: case content::PermissionType::WAKE_LOCK_SYSTEM: + case content::PermissionType::NFC: + case content::PermissionType::AR: + case content::PermissionType::VR: + case content::PermissionType::STORAGE_ACCESS_GRANT: + case content::PermissionType::WINDOW_PLACEMENT: + case content::PermissionType::FONT_ACCESS: case content::PermissionType::NUM: - NOTIMPLEMENTED() << "Unsupported permission type: " << static_cast<int>(type); + LOG(INFO) << "Unexpected unsupported permission type: " << static_cast<int>(type); break; } return ProfileAdapter::UnsupportedPermission; } +static bool canRequestPermissionFor(ProfileAdapter::PermissionType type) +{ + switch (type) { + case ProfileAdapter::GeolocationPermission: + case ProfileAdapter::NotificationPermission: + return true; + default: + break; + } + return false; +} + +static blink::mojom::PermissionStatus toBlink(ProfileAdapter::PermissionState reply) +{ + switch (reply) { + case ProfileAdapter::AskPermission: + return blink::mojom::PermissionStatus::ASK; + case ProfileAdapter::AllowedPermission: + return blink::mojom::PermissionStatus::GRANTED; + case ProfileAdapter::DeniedPermission: + return blink::mojom::PermissionStatus::DENIED; + } +} + PermissionManagerQt::PermissionManagerQt() : m_requestIdCount(0) - , m_subscriberIdCount(0) { } @@ -98,12 +129,20 @@ PermissionManagerQt::~PermissionManagerQt() { } -void PermissionManagerQt::permissionRequestReply(const QUrl &origin, ProfileAdapter::PermissionType type, bool reply) +void PermissionManagerQt::permissionRequestReply(const QUrl &url, ProfileAdapter::PermissionType type, ProfileAdapter::PermissionState reply) { + // Normalize the QUrl to GURL origin form. + const GURL gorigin = toGurl(url).GetOrigin(); + const QUrl origin = gorigin.is_empty() ? url : toQt(gorigin); + if (origin.isEmpty()) + return; QPair<QUrl, ProfileAdapter::PermissionType> key(origin, type); - m_permissions[key] = reply; - blink::mojom::PermissionStatus status = reply ? blink::mojom::PermissionStatus::GRANTED : blink::mojom::PermissionStatus::DENIED; - { + if (reply == ProfileAdapter::AskPermission) + m_permissions.remove(key); + else + m_permissions[key] = (reply == ProfileAdapter::AllowedPermission); + blink::mojom::PermissionStatus status = toBlink(reply); + if (reply != ProfileAdapter::AskPermission) { auto it = m_requests.begin(); while (it != m_requests.end()) { if (it->origin == origin && it->type == type) { @@ -118,6 +157,9 @@ void PermissionManagerQt::permissionRequestReply(const QUrl &origin, ProfileAdap it.second.callback.Run(status); } + if (reply == ProfileAdapter::AskPermission) + return; + auto it = m_multiRequests.begin(); while (it != m_multiRequests.end()) { if (it->origin == origin) { @@ -163,15 +205,17 @@ int PermissionManagerQt::RequestPermission(content::PermissionType permission, bool /*user_gesture*/, base::OnceCallback<void(blink::mojom::PermissionStatus)> callback) { + if (requesting_origin.is_empty()) { + std::move(callback).Run(blink::mojom::PermissionStatus::DENIED); + return content::PermissionController::kNoPendingOperation; + } + WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt *>( content::WebContents::FromRenderFrameHost(frameHost)->GetDelegate()); Q_ASSERT(contentsDelegate); ProfileAdapter::PermissionType permissionType = toQt(permission); - if (permissionType == ProfileAdapter::UnsupportedPermission) { - std::move(callback).Run(blink::mojom::PermissionStatus::DENIED); - return content::PermissionController::kNoPendingOperation; - } else if (permissionType == ProfileAdapter::ClipboardRead) { + if (permissionType == ProfileAdapter::ClipboardRead) { WebEngineSettings *settings = contentsDelegate->webEngineSettings(); if (settings->testAttribute(WebEngineSettings::JavascriptCanAccessClipboard) && settings->testAttribute(WebEngineSettings::JavascriptCanPaste)) @@ -179,19 +223,15 @@ int PermissionManagerQt::RequestPermission(content::PermissionType permission, else std::move(callback).Run(blink::mojom::PermissionStatus::DENIED); return content::PermissionController::kNoPendingOperation; + } else if (!canRequestPermissionFor(permissionType)) { + std::move(callback).Run(blink::mojom::PermissionStatus::DENIED); + return content::PermissionController::kNoPendingOperation; } - // Audio and video-capture should not come this way currently - Q_ASSERT(permissionType != ProfileAdapter::AudioCapturePermission - && permissionType != ProfileAdapter::VideoCapturePermission); int request_id = ++m_requestIdCount; auto requestOrigin = toQt(requesting_origin); m_requests.push_back({ request_id, permissionType, requestOrigin, std::move(callback) }); - if (permissionType == ProfileAdapter::GeolocationPermission) - contentsDelegate->requestGeolocationPermission(requestOrigin); - else if (permissionType == ProfileAdapter::NotificationPermission) - contentsDelegate->requestUserNotificationPermission(requestOrigin); - + contentsDelegate->requestFeaturePermission(permissionType, requestOrigin); return request_id; } @@ -201,6 +241,11 @@ int PermissionManagerQt::RequestPermissions(const std::vector<content::Permissio bool /*user_gesture*/, base::OnceCallback<void(const std::vector<blink::mojom::PermissionStatus>&)> callback) { + if (requesting_origin.is_empty()) { + std::move(callback).Run(std::vector<blink::mojom::PermissionStatus>(permissions.size(), blink::mojom::PermissionStatus::DENIED)); + return content::PermissionController::kNoPendingOperation; + } + WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt *>( content::WebContents::FromRenderFrameHost(frameHost)->GetDelegate()); Q_ASSERT(contentsDelegate); @@ -234,10 +279,8 @@ int PermissionManagerQt::RequestPermissions(const std::vector<content::Permissio m_multiRequests.push_back({ request_id, permissions, requestOrigin, std::move(callback) }); for (content::PermissionType permission : permissions) { const ProfileAdapter::PermissionType permissionType = toQt(permission); - if (permissionType == ProfileAdapter::GeolocationPermission) - contentsDelegate->requestGeolocationPermission(requestOrigin); - else if (permissionType == ProfileAdapter::NotificationPermission) - contentsDelegate->requestUserNotificationPermission(requestOrigin); + if (canRequestPermissionFor(permissionType)) + contentsDelegate->requestFeaturePermission(permissionType, requestOrigin); } return request_id; } @@ -264,13 +307,13 @@ blink::mojom::PermissionStatus PermissionManagerQt::GetPermissionStatusForFrame( content::RenderFrameHost *render_frame_host, const GURL &requesting_origin) { - if (permission == content::PermissionType::CLIPBOARD_READ || - permission == content::PermissionType::CLIPBOARD_WRITE) { + if (permission == content::PermissionType::CLIPBOARD_READ_WRITE || + permission == content::PermissionType::CLIPBOARD_SANITIZED_WRITE) { WebContentsDelegateQt *delegate = static_cast<WebContentsDelegateQt *>( content::WebContents::FromRenderFrameHost(render_frame_host)->GetDelegate()); if (!delegate->webEngineSettings()->testAttribute(WebEngineSettings::JavascriptCanAccessClipboard)) return blink::mojom::PermissionStatus::DENIED; - if (permission == content::PermissionType::CLIPBOARD_READ && + if (permission == content::PermissionType::CLIPBOARD_READ_WRITE && !delegate->webEngineSettings()->testAttribute(WebEngineSettings::JavascriptCanPaste)) return blink::mojom::PermissionStatus::DENIED; return blink::mojom::PermissionStatus::GRANTED; @@ -295,19 +338,19 @@ void PermissionManagerQt::ResetPermission( m_permissions.remove(key); } -int PermissionManagerQt::SubscribePermissionStatusChange( +content::PermissionControllerDelegate::SubscriptionId PermissionManagerQt::SubscribePermissionStatusChange( content::PermissionType permission, content::RenderFrameHost * /* render_frame_host */, const GURL& requesting_origin, base::RepeatingCallback<void(blink::mojom::PermissionStatus)> callback) { - int subscriber_id = ++m_subscriberIdCount; + auto subscriber_id = subscription_id_generator_.GenerateNextId(); m_subscribers.insert( { subscriber_id, Subscription { toQt(permission), toQt(requesting_origin), std::move(callback) } }); return subscriber_id; } -void PermissionManagerQt::UnsubscribePermissionStatusChange(int subscription_id) +void PermissionManagerQt::UnsubscribePermissionStatusChange(content::PermissionControllerDelegate::SubscriptionId subscription_id) { if (!m_subscribers.erase(subscription_id)) LOG(WARNING) << "PermissionManagerQt::UnsubscribePermissionStatusChange called on unknown subscription id" << subscription_id; diff --git a/src/core/permission_manager_qt.h b/src/core/permission_manager_qt.h index 6ab071237..f8d7e0ee3 100644 --- a/src/core/permission_manager_qt.h +++ b/src/core/permission_manager_qt.h @@ -54,10 +54,9 @@ class PermissionManagerQt : public content::PermissionControllerDelegate { public: PermissionManagerQt(); ~PermissionManagerQt(); - typedef ProfileAdapter::PermissionType PermissionType; - void permissionRequestReply(const QUrl &origin, PermissionType type, bool reply); - bool checkPermission(const QUrl &origin, PermissionType type); + void permissionRequestReply(const QUrl &origin, ProfileAdapter::PermissionType type, ProfileAdapter::PermissionState reply); + bool checkPermission(const QUrl &origin, ProfileAdapter::PermissionType type); // content::PermissionManager implementation: int RequestPermission( @@ -90,19 +89,19 @@ public: base::OnceCallback<void( const std::vector<blink::mojom::PermissionStatus>&)> callback) override; - int SubscribePermissionStatusChange( + content::PermissionControllerDelegate::SubscriptionId SubscribePermissionStatusChange( content::PermissionType permission, content::RenderFrameHost* render_frame_host, const GURL& requesting_origin, const base::RepeatingCallback<void(blink::mojom::PermissionStatus)> callback) override; - void UnsubscribePermissionStatusChange(int subscription_id) override; + void UnsubscribePermissionStatusChange(content::PermissionControllerDelegate::SubscriptionId subscription_id) override; private: - QHash<QPair<QUrl, PermissionType>, bool> m_permissions; + QHash<QPair<QUrl, ProfileAdapter::PermissionType>, bool> m_permissions; struct Request { int id; - PermissionType type; + ProfileAdapter::PermissionType type; QUrl origin; base::OnceCallback<void(blink::mojom::PermissionStatus)> callback; }; @@ -113,15 +112,15 @@ private: base::OnceCallback<void(const std::vector<blink::mojom::PermissionStatus>&)> callback; }; struct Subscription { - PermissionType type; + ProfileAdapter::PermissionType type; QUrl origin; base::RepeatingCallback<void(blink::mojom::PermissionStatus)> callback; }; std::vector<Request> m_requests; std::vector<MultiRequest> m_multiRequests; - std::map<int, Subscription> m_subscribers; + std::map<content::PermissionControllerDelegate::SubscriptionId, Subscription> m_subscribers; + content::PermissionControllerDelegate::SubscriptionId::Generator subscription_id_generator_; int m_requestIdCount; - int m_subscriberIdCount; }; diff --git a/src/core/platform_notification_service_qt.cpp b/src/core/platform_notification_service_qt.cpp index d8abec17f..5f3017dcf 100644 --- a/src/core/platform_notification_service_qt.cpp +++ b/src/core/platform_notification_service_qt.cpp @@ -201,12 +201,11 @@ int64_t PlatformNotificationServiceQt::ReadNextPersistentNotificationId() void PlatformNotificationServiceQt::ScheduleTrigger(base::Time /*timestamp*/) { - Q_UNIMPLEMENTED(); + QT_NOT_YET_IMPLEMENTED } base::Time PlatformNotificationServiceQt::ReadNextTriggerTimestamp() { - Q_UNIMPLEMENTED(); return base::Time::Max(); } diff --git a/src/core/pref_service_adapter.cpp b/src/core/pref_service_adapter.cpp index ca4be87df..ff653c066 100644 --- a/src/core/pref_service_adapter.cpp +++ b/src/core/pref_service_adapter.cpp @@ -39,12 +39,13 @@ #include "pref_service_adapter.h" -#include "command_line_pref_store_qt.h" #include "profile_adapter.h" #include "type_conversion.h" #include "web_engine_context.h" +#include "chrome/browser/prefs/chrome_command_line_pref_store.h" #include "content/public/browser/browser_thread.h" +#include "components/language/core/browser/pref_names.h" #include "components/prefs/pref_member.h" #include "components/prefs/in_memory_pref_store.h" #include "components/prefs/json_pref_store.h" @@ -80,11 +81,11 @@ void PrefServiceAdapter::setup(const ProfileAdapter &profileAdapter) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); PrefServiceFactory factory; - factory.set_command_line_prefs(base::MakeRefCounted<CommandLinePrefStoreQt>( + factory.set_command_line_prefs(base::MakeRefCounted<ChromeCommandLinePrefStore>( WebEngineContext::commandLine())); QString userPrefStorePath = profileAdapter.dataPath(); - if (userPrefStorePath.isEmpty() || profileAdapter.isOffTheRecord()) { + if (profileAdapter.isOffTheRecord() || profileAdapter.storageName().isEmpty()) { factory.set_user_prefs(new InMemoryPrefStore); } else { userPrefStorePath += QDir::separator(); @@ -92,15 +93,15 @@ void PrefServiceAdapter::setup(const ProfileAdapter &profileAdapter) factory.set_user_prefs(base::MakeRefCounted<JsonPrefStore>(toFilePath(userPrefStorePath))); } - PrefRegistrySimple *registry = new PrefRegistrySimple(); - PrefProxyConfigTrackerImpl::RegisterPrefs(registry); + auto registry = base::MakeRefCounted<PrefRegistrySimple>(); + PrefProxyConfigTrackerImpl::RegisterPrefs(registry.get()); #if QT_CONFIG(webengine_spellchecker) // Initial spellcheck settings - registry->RegisterStringPref(prefs::kAcceptLanguages, std::string()); + registry->RegisterStringPref(language::prefs::kAcceptLanguages, std::string()); registry->RegisterListPref(spellcheck::prefs::kSpellCheckDictionaries); registry->RegisterListPref(spellcheck::prefs::kSpellCheckForcedDictionaries); - registry->RegisterListPref(spellcheck::prefs::kSpellCheckBlacklistedDictionaries); + registry->RegisterListPref(spellcheck::prefs::kSpellCheckBlocklistedDictionaries); registry->RegisterStringPref(spellcheck::prefs::kSpellCheckDictionary, std::string()); registry->RegisterBooleanPref(spellcheck::prefs::kSpellCheckEnable, false); registry->RegisterBooleanPref(spellcheck::prefs::kSpellCheckUseSpellingService, false); @@ -119,10 +120,9 @@ void PrefServiceAdapter::setup(const ProfileAdapter &profileAdapter) registry->RegisterBooleanPref(extensions::pref_names::kStorageGarbageCollect, false); registry->RegisterListPref(extensions::pref_names::kAllowedInstallSites); registry->RegisterStringPref(extensions::pref_names::kLastChromeVersion, std::string()); - registry->RegisterListPref(extensions::pref_names::kNativeMessagingBlacklist); - registry->RegisterListPref(extensions::pref_names::kNativeMessagingWhitelist); + registry->RegisterListPref(extensions::pref_names::kNativeMessagingBlocklist); + registry->RegisterListPref(extensions::pref_names::kNativeMessagingAllowlist); registry->RegisterBooleanPref(extensions::pref_names::kNativeMessagingUserLevelHosts, true); - registry->RegisterBooleanPref(extensions::pref_names::kInsecureExtensionUpdatesEnabled, false); #endif // BUILDFLAG(ENABLE_EXTENSIONS) // Media device salt id key diff --git a/src/core/printing/print_view_manager_base_qt.cpp b/src/core/printing/print_view_manager_base_qt.cpp index 4516f10b2..fe365df53 100644 --- a/src/core/printing/print_view_manager_base_qt.cpp +++ b/src/core/printing/print_view_manager_base_qt.cpp @@ -48,10 +48,9 @@ #include "web_engine_context.h" #include "base/memory/ref_counted_memory.h" -#include "base/memory/shared_memory.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" +#include "base/task/current_thread.h" #include "base/task/post_task.h" #include "base/timer/timer.h" #include "base/values.h" @@ -59,10 +58,13 @@ #include "chrome/browser/printing/print_job.h" #include "chrome/browser/printing/print_job_manager.h" #include "chrome/browser/printing/printer_query.h" +#include "components/printing/browser/print_manager_utils.h" +#include "components/printing/common/print.mojom.h" #include "components/printing/common/print_messages.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_types.h" @@ -72,12 +74,71 @@ namespace QtWebEngineCore { +namespace { + +// Runs |callback| with |params| to reply to +// mojom::PrintManagerHost::GetDefaultPrintSettings. +void GetDefaultPrintSettingsReply(printing::mojom::PrintManagerHost::GetDefaultPrintSettingsCallback callback, + printing::mojom::PrintParamsPtr params) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + std::move(callback).Run(std::move(params)); +} + +void GetDefaultPrintSettingsReplyOnIO(scoped_refptr<printing::PrintQueriesQueue> queue, + std::unique_ptr<printing::PrinterQuery> printer_query, + printing::mojom::PrintManagerHost::GetDefaultPrintSettingsCallback callback) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + printing::mojom::PrintParamsPtr params = printing::mojom::PrintParams::New(); + if (printer_query && printer_query->last_status() == printing::PrintingContext::OK) { + RenderParamsFromPrintSettings(printer_query->settings(), params.get()); + params->document_cookie = printer_query->cookie(); + } + + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, + base::BindOnce(&GetDefaultPrintSettingsReply, + std::move(callback), std::move(params))); + + // If printing was enabled. + if (printer_query) { + // If user hasn't cancelled. + if (printer_query->cookie() && printer_query->settings().dpi()) { + queue->QueuePrinterQuery(std::move(printer_query)); + } else { + printer_query->StopWorker(); + } + } +} + +void GetDefaultPrintSettingsOnIO(printing::mojom::PrintManagerHost::GetDefaultPrintSettingsCallback callback, + scoped_refptr<printing::PrintQueriesQueue> queue, + int process_id, int routing_id) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + std::unique_ptr<printing::PrinterQuery> printer_query = queue->PopPrinterQuery(0); + if (!printer_query) + printer_query = queue->CreatePrinterQuery(process_id, routing_id); + + // Loads default settings. This is asynchronous, only the mojo message sender + // will hang until the settings are retrieved. + auto *printer_query_ptr = printer_query.get(); + printer_query_ptr->GetSettings( + printing::PrinterQuery::GetSettingsAskParam::DEFAULTS, 0, false, + printing::mojom::MarginType::kDefaultMargins, false, false, + base::BindOnce(&GetDefaultPrintSettingsReplyOnIO, queue, + std::move(printer_query), std::move(callback))); +} + +} // namespace + PrintViewManagerBaseQt::PrintViewManagerBaseQt(content::WebContents *contents) : printing::PrintManager(contents) - , m_isInsideInnerMessageLoop(false) + , m_printingRFH(nullptr) , m_didPrintingSucceed(false) , m_printerQueriesQueue(WebEngineContext::current()->getPrintJobManager()->queue()) - , m_printingRFH(nullptr) { // FIXME: Check if this needs to be executed async: // TODO: Add isEnabled to profile @@ -119,44 +180,47 @@ base::string16 PrintViewManagerBaseQt::RenderSourceName() return toString16(QLatin1String("")); } -void PrintViewManagerBaseQt::PrintDocument(printing::PrintedDocument *document, - const scoped_refptr<base::RefCountedMemory> &print_data, +void PrintViewManagerBaseQt::PrintDocument(scoped_refptr<base::RefCountedMemory> print_data, const gfx::Size &page_size, const gfx::Rect &content_area, const gfx::Point &offsets) { std::unique_ptr<printing::MetafileSkia> metafile = std::make_unique<printing::MetafileSkia>(); - CHECK(metafile->InitFromData(print_data->front(), print_data->size())); + CHECK(metafile->InitFromData(*print_data)); // Update the rendered document. It will send notifications to the listener. - document->SetDocument(std::move(metafile), page_size, content_area); + printing::PrintedDocument* document = m_printJob->document(); + document->SetDocument(std::move(metafile)); ShouldQuitFromInnerMessageLoop(); } -printing::PrintedDocument *PrintViewManagerBaseQt::GetDocument(int cookie) +void PrintViewManagerBaseQt::DidGetPrintedPagesCount(int32_t cookie, uint32_t number_pages) +{ + PrintManager::DidGetPrintedPagesCount(cookie, number_pages); + OpportunisticallyCreatePrintJob(cookie); +} + +bool PrintViewManagerBaseQt::PrintJobHasDocument(int cookie) { if (!OpportunisticallyCreatePrintJob(cookie)) - return nullptr; + return false; + // These checks may fail since we are completely asynchronous. Old spurious + // messages can be received if one of the processes is overloaded. printing::PrintedDocument* document = m_printJob->document(); - if (!document || cookie != document->cookie()) { - // Out of sync. It may happen since we are completely asynchronous. Old - // spurious messages can be received if one of the processes is overloaded. - return nullptr; - } - return document; + return document && document->cookie() == cookie; } // IPC handlers void PrintViewManagerBaseQt::OnDidPrintDocument(content::RenderFrameHost* /*render_frame_host*/, - const PrintHostMsg_DidPrintDocument_Params ¶ms) + const printing::mojom::DidPrintDocumentParams ¶ms, + std::unique_ptr<DelayedFrameDispatchHelper> helper) { - printing::PrintedDocument *document = GetDocument(params.document_cookie); - if (!document) + if (!PrintJobHasDocument(params.document_cookie)) return; - const PrintHostMsg_DidPrintContent_Params &content = params.content; + const printing::mojom::DidPrintContentParams &content = *params.content; if (!content.metafile_data_region.IsValid()) { NOTREACHED() << "invalid memory handle"; web_contents()->Stop(); @@ -170,11 +234,49 @@ void PrintViewManagerBaseQt::OnDidPrintDocument(content::RenderFrameHost* /*rend return; } - PrintDocument(document, data, params.page_size, params.content_area, + PrintDocument(data, params.page_size, params.content_area, params.physical_offsets); + if (helper) + helper->SendCompleted(); +} + +void PrintViewManagerBaseQt::GetDefaultPrintSettings(GetDefaultPrintSettingsCallback callback) +{ + content::RenderFrameHost* render_frame_host = + print_manager_host_receivers_.GetCurrentTargetFrame(); + + content::GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, + base::BindOnce(&GetDefaultPrintSettingsOnIO, std::move(callback), m_printerQueriesQueue, + render_frame_host->GetProcess()->GetID(), + render_frame_host->GetRoutingID())); +} + +void PrintViewManagerBaseQt::PrintingFailed(int32_t cookie) +{ + // Note: Not redundant with cookie checks in the same method in other parts of + // the class hierarchy. + if (!IsValidCookie(cookie)) + return; + + PrintManager::PrintingFailed(cookie); + + ReleasePrinterQuery(); + + content::NotificationService::current()->Notify( + chrome::NOTIFICATION_PRINT_JOB_RELEASED, + content::Source<content::WebContents>(web_contents()), + content::NotificationService::NoDetails()); } -void PrintViewManagerBaseQt::OnShowInvalidPrinterSettingsError() +void PrintViewManagerBaseQt::OnScriptedPrint(content::RenderFrameHost *render_frame_host, + const printing::mojom::ScriptedPrintParams ¶ms, + IPC::Message *reply_msg) +{ + NOTREACHED() << "should be handled by printing::PrintingMessageFilter"; +} + +void PrintViewManagerBaseQt::ShowInvalidPrinterSettingsError() { } @@ -187,6 +289,8 @@ void PrintViewManagerBaseQt::DidStartLoading() // so m_printingRFH is never set and used at the moment. void PrintViewManagerBaseQt::RenderFrameDeleted(content::RenderFrameHost *render_frame_host) { + PrintManager::RenderFrameDeleted(render_frame_host); + // Terminates or cancels the print job if one was pending. if (render_frame_host != m_printingRFH) return; @@ -200,7 +304,7 @@ void PrintViewManagerBaseQt::RenderFrameDeleted(content::RenderFrameHost *render return; scoped_refptr<printing::PrintedDocument> document(m_printJob->document()); - if (document.get()) { + if (document) { // If IsComplete() returns false, the document isn't completely rendered. // Since our renderer is gone, there's nothing to do, cancel it. Otherwise, // the print job may finish without problem. @@ -208,25 +312,6 @@ void PrintViewManagerBaseQt::RenderFrameDeleted(content::RenderFrameHost *render } } -bool PrintViewManagerBaseQt::OnMessageReceived(const IPC::Message& message, - content::RenderFrameHost* render_frame_host) -{ - bool handled = true; - IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(PrintViewManagerBaseQt, message, render_frame_host) - IPC_MESSAGE_HANDLER(PrintHostMsg_DidPrintDocument, OnDidPrintDocument) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - if (handled) - return true; - handled = true; - IPC_BEGIN_MESSAGE_MAP(PrintViewManagerBaseQt, message) - IPC_MESSAGE_HANDLER(PrintHostMsg_ShowInvalidPrinterSettingsError, - OnShowInvalidPrinterSettingsError); - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled || PrintManager::OnMessageReceived(message, render_frame_host); -} - void PrintViewManagerBaseQt::Observe(int type, const content::NotificationSource& /*source*/, const content::NotificationDetails& details) @@ -324,28 +409,21 @@ bool PrintViewManagerBaseQt::RenderAllMissingPagesNow() return true; } -// Quits the current message loop if these conditions hold true: a document is -// loaded and is complete and waiting_for_pages_to_be_rendered_ is true. This -// function is called in DidPrintPage() or on ALL_PAGES_REQUESTED -// notification. The inner message loop is created was created by -// RenderAllMissingPagesNow(). void PrintViewManagerBaseQt::ShouldQuitFromInnerMessageLoop() { // Look at the reason. DCHECK(m_printJob->document()); - if (m_printJob->document() && - m_printJob->document()->IsComplete() && - m_isInsideInnerMessageLoop) { - // We are in a message loop created by RenderAllMissingPagesNow. Quit from - // it. - base::RunLoop::QuitCurrentWhenIdleDeprecated(); - m_isInsideInnerMessageLoop = false; + if (m_printJob->document() && m_printJob->document()->IsComplete() && m_quitInnerLoop) { + // We are in a message loop created by RenderAllMissingPagesNow. Quit from + // it. + std::move(m_quitInnerLoop).Run(); } } bool PrintViewManagerBaseQt::CreateNewPrintJob(std::unique_ptr<printing::PrinterQuery> query) { - DCHECK(!m_isInsideInnerMessageLoop); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + DCHECK(!m_quitInnerLoop); DCHECK(query); // Disconnect the current |m_printJob|. @@ -396,9 +474,9 @@ void PrintViewManagerBaseQt::TerminatePrintJob(bool cancel) if (cancel) { // We don't need the metafile data anymore because the printing is canceled. m_printJob->Cancel(); - m_isInsideInnerMessageLoop = false; + m_quitInnerLoop.Reset(); } else { - DCHECK(!m_isInsideInnerMessageLoop); + DCHECK(!m_quitInnerLoop); DCHECK(!m_printJob->document() || m_printJob->document()->IsComplete()); // WebContents is either dying or navigating elsewhere. We need to render @@ -417,12 +495,8 @@ void PrintViewManagerBaseQt::ReleasePrintJob() if (!m_printJob.get()) return; - if (rfh) { - auto msg = std::make_unique<PrintMsg_PrintingDone>(rfh->GetRoutingID(), - m_didPrintingSucceed); - rfh->Send(msg.release()); - } - + if (rfh) + GetPrintRenderFrame(rfh)->PrintingDone(m_didPrintingSucceed); m_registrar.Remove(this, chrome::NOTIFICATION_PRINT_JOB_EVENT, content::Source<printing::PrintJob>(m_printJob.get())); @@ -430,7 +504,8 @@ void PrintViewManagerBaseQt::ReleasePrintJob() m_printJob = nullptr; } -bool PrintViewManagerBaseQt::RunInnerMessageLoop() { +bool PrintViewManagerBaseQt::RunInnerMessageLoop() +{ // This value may actually be too low: // // - If we're looping because of printer settings initialization, the premise @@ -449,20 +524,16 @@ bool PrintViewManagerBaseQt::RunInnerMessageLoop() { base::TimeDelta::FromMilliseconds(kPrinterSettingsTimeout), run_loop.QuitWhenIdleClosure()); - m_isInsideInnerMessageLoop = true; + m_quitInnerLoop = run_loop.QuitClosure(); // Need to enable recursive task. { - base::MessageLoopCurrent::ScopedNestableTaskAllower allow; + base::CurrentThread::ScopedNestableTaskAllower allow; run_loop.Run(); } - bool success = true; - if (m_isInsideInnerMessageLoop) { - // Ok we timed out. That's sad. - m_isInsideInnerMessageLoop = false; - success = false; - } + bool success = !m_quitInnerLoop; + m_quitInnerLoop.Reset(); return success; } @@ -514,25 +585,26 @@ void PrintViewManagerBaseQt::ReleasePrinterQuery() printerQuery = m_printerQueriesQueue->PopPrinterQuery(cookie); if (!printerQuery) return; - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&printing::PrinterQuery::StopWorker, std::move(printerQuery))); + base::PostTask(FROM_HERE, {content::BrowserThread::IO}, + base::BindOnce(&printing::PrinterQuery::StopWorker, std::move(printerQuery))); } // Originally from print_preview_message_handler.cc: -void PrintViewManagerBaseQt::StopWorker(int documentCookie) { - if (documentCookie <= 0) - return; - std::unique_ptr<printing::PrinterQuery> printer_query = - m_printerQueriesQueue->PopPrinterQuery(documentCookie); - if (printer_query.get()) { - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&printing::PrinterQuery::StopWorker, std::move(printer_query))); - } +void PrintViewManagerBaseQt::StopWorker(int documentCookie) +{ + if (documentCookie <= 0) + return; + std::unique_ptr<printing::PrinterQuery> printer_query = + m_printerQueriesQueue->PopPrinterQuery(documentCookie); + if (printer_query.get()) { + base::PostTask(FROM_HERE, {content::BrowserThread::IO}, + base::BindOnce(&printing::PrinterQuery::StopWorker, std::move(printer_query))); + } } void PrintViewManagerBaseQt::SendPrintingEnabled(bool enabled, content::RenderFrameHost* rfh) { - rfh->Send(new PrintMsg_SetPrintingEnabled(rfh->GetRoutingID(), enabled)); + GetPrintRenderFrame(rfh)->SetPrintingEnabled(enabled); } } // namespace QtWebEngineCore diff --git a/src/core/printing/print_view_manager_base_qt.h b/src/core/printing/print_view_manager_base_qt.h index 31e0a1778..3086d5d3a 100644 --- a/src/core/printing/print_view_manager_base_qt.h +++ b/src/core/printing/print_view_manager_base_qt.h @@ -48,27 +48,22 @@ #include "base/strings/string16.h" #include "components/prefs/pref_member.h" #include "components/printing/browser/print_manager.h" +#include "components/printing/common/print.mojom-forward.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" -struct PrintHostMsg_DidPrintDocument_Params; - namespace base { class RefCountedBytes; } namespace content { class RenderFrameHost; -class RenderViewHost; } namespace printing { class JobEventDetails; -class MetafilePlayer; class PrintJob; -class PrintJobWorkerOwner; class PrintQueriesQueue; -class PrintedDocument; class PrinterQuery; } @@ -82,55 +77,70 @@ public: // Whether printing is enabled or not. void UpdatePrintingEnabled(); - virtual base::string16 RenderSourceName(); + base::string16 RenderSourceName(); + + // mojom::PrintManagerHost: + void DidGetPrintedPagesCount(int32_t cookie, uint32_t number_pages) override; + void GetDefaultPrintSettings(GetDefaultPrintSettingsCallback callback) override; + void ShowInvalidPrinterSettingsError() override; + void PrintingFailed(int32_t cookie) override; protected: explicit PrintViewManagerBaseQt(content::WebContents*); void SetPrintingRFH(content::RenderFrameHost* rfh); - // content::WebContentsObserver implementation. // Cancels the print job. void NavigationStopped() override; // content::WebContentsObserver implementation. void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override; - bool OnMessageReceived(const IPC::Message& message, - content::RenderFrameHost* render_frame_host) override; - // IPC Message handlers. - void OnDidPrintDocument(content::RenderFrameHost* render_frame_host, - const PrintHostMsg_DidPrintDocument_Params& params); - void OnShowInvalidPrinterSettingsError(); + // Creates a new empty print job. It has no settings loaded. If there is + // currently a print job, safely disconnect from it. Returns false if it is + // impossible to safely disconnect from the current print job or it is + // impossible to create a new print job. + virtual bool CreateNewPrintJob(std::unique_ptr<printing::PrinterQuery> query); - // Processes a NOTIFY_PRINT_JOB_EVENT notification. - void OnNotifyPrintJobEvent(const printing::JobEventDetails& event_details); + // Makes sure the current print_job_ has all its data before continuing, and + // disconnect from it. + void DisconnectFromCurrentPrintJob(); + void StopWorker(int documentCookie); + +private: // content::NotificationObserver implementation. void Observe(int, const content::NotificationSource&, const content::NotificationDetails&) override; - void StopWorker(int document_cookie); - // In the case of Scripted Printing, where the renderer is controlling the - // control flow, print_job_ is initialized whenever possible. No-op is - // print_job_ is initialized. - bool OpportunisticallyCreatePrintJob(int cookie); + // content::WebContentsObserver implementation. + void DidStartLoading() override; + + // printing::PrintManager: + void OnDidPrintDocument( + content::RenderFrameHost *render_frame_host, + const printing::mojom::DidPrintDocumentParams ¶ms, + std::unique_ptr<DelayedFrameDispatchHelper> helper) override; + void OnScriptedPrint(content::RenderFrameHost *render_frame_host, + const printing::mojom::ScriptedPrintParams ¶ms, + IPC::Message *reply_msg) override; + + // Processes a NOTIFY_PRINT_JOB_EVENT notification. + void OnNotifyPrintJobEvent(const printing::JobEventDetails &event_details); // Requests the RenderView to render all the missing pages for the print job. // No-op if no print job is pending. Returns true if at least one page has // been requested to the renderer. bool RenderAllMissingPagesNow(); - // Checks that synchronization is correct and a print query exists for - // |cookie|. If so, returns the document associated with the cookie. - printing::PrintedDocument* GetDocument(int cookie); + // Checks that synchronization is correct with |print_job_| based on |cookie|. + bool PrintJobHasDocument(int cookie); - // Starts printing a document with data given in |print_data|. |print_data| - // must successfully initialize a metafile. |document| is the printed - // document associated with the print job. Returns true if successful. - void PrintDocument(printing::PrintedDocument *document, - const scoped_refptr<base::RefCountedMemory> &print_data, + // Starts printing the |document| in |print_job_| with the given |print_data|. + // This method assumes PrintJobHasDocument() has been called, and |print_data| + // contains valid data. + void PrintDocument(scoped_refptr<base::RefCountedMemory> print_data, const gfx::Size &page_size, const gfx::Rect &content_area, const gfx::Point &offsets); @@ -142,29 +152,43 @@ protected: // RenderAllMissingPagesNow(). void ShouldQuitFromInnerMessageLoop(); - bool RunInnerMessageLoop(); - + // Terminates the print job. No-op if no print job has been created. If + // |cancel| is true, cancel it instead of waiting for the job to finish. Will + // call ReleasePrintJob(). void TerminatePrintJob(bool cancel); - void DisconnectFromCurrentPrintJob(); - bool CreateNewPrintJob(std::unique_ptr<printing::PrinterQuery> query); + // Releases print_job_. Correctly deregisters from notifications. No-op if + // no print job has been created. void ReleasePrintJob(); + + // Runs an inner message loop. It will set inside_inner_message_loop_ to true + // while the blocking inner message loop is running. This is useful in cases + // where the RenderView is about to be destroyed while a printing job isn't + // finished. + bool RunInnerMessageLoop(); + + // In the case of Scripted Printing, where the renderer is controlling the + // control flow, print_job_ is initialized whenever possible. No-op is + // print_job_ is initialized. + bool OpportunisticallyCreatePrintJob(int cookie); + + // Release the PrinterQuery associated with our |cookie_|. void ReleasePrinterQuery(); -private: // Helper method for UpdatePrintingEnabled(). void SendPrintingEnabled(bool enabled, content::RenderFrameHost* rfh); - // content::WebContentsObserver implementation. - void DidStartLoading() override; private: content::NotificationRegistrar m_registrar; scoped_refptr<printing::PrintJob> m_printJob; - bool m_isInsideInnerMessageLoop; + content::RenderFrameHost *m_printingRFH; bool m_didPrintingSucceed; + // Set while running an inner message loop inside RenderAllMissingPagesNow(). + // This means we are _blocking_ until all the necessary pages have been + // rendered or the print settings are being loaded. + base::OnceClosure m_quitInnerLoop; scoped_refptr<printing::PrintQueriesQueue> m_printerQueriesQueue; - // The current RFH that is printing with a system printing dialog. - content::RenderFrameHost *m_printingRFH; + DISALLOW_COPY_AND_ASSIGN(PrintViewManagerBaseQt); }; diff --git a/src/core/printing/print_view_manager_qt.cpp b/src/core/printing/print_view_manager_qt.cpp index 7d8039100..de1b81fb9 100644 --- a/src/core/printing/print_view_manager_qt.cpp +++ b/src/core/printing/print_view_manager_qt.cpp @@ -37,6 +37,7 @@ ** ****************************************************************************/ +// Loosely based on print_view_manager.cc and print_preview_message_handler.cc // Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE.Chromium file. @@ -56,16 +57,17 @@ #include "base/task/post_task.h" #include "chrome/browser/printing/print_job_manager.h" #include "chrome/browser/printing/printer_query.h" +#include "components/printing/common/print.mojom.h" #include "components/printing/common/print_messages.h" #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_frame_host.h" -#include "content/public/common/web_preferences.h" #include "printing/metafile_skia.h" #include "printing/print_job_constants.h" #include "printing/units.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" namespace { @@ -101,13 +103,13 @@ static void SavePdfFile(scoped_refptr<base::RefCountedBytes> data, DCHECK_GT(data->size(), 0U); printing::MetafileSkia metafile; - metafile.InitFromData(static_cast<const void*>(data->front()), data->size()); + metafile.InitFromData(base::as_bytes(base::make_span(data->front(), data->size()))); base::File file(path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); bool success = file.IsValid() && metafile.SaveTo(&file); - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(saveCallback, success)); + base::PostTask(FROM_HERE, {content::BrowserThread::UI}, + base::BindOnce(saveCallback, success)); } static base::DictionaryValue *createPrintSettings() @@ -120,15 +122,12 @@ static base::DictionaryValue *createPrintSettings() printSettings->SetInteger(printing::kPreviewRequestID, internalRequestId); // The following are standard settings that Chromium expects to be set. - printSettings->SetBoolean(printing::kSettingPrintToPDF, true); - printSettings->SetBoolean(printing::kSettingCloudPrintDialog, false); - printSettings->SetBoolean(printing::kSettingPrintWithPrivet, false); - printSettings->SetBoolean(printing::kSettingPrintWithExtension, false); + printSettings->SetInteger(printing::kSettingPrinterType, static_cast<int>(printing::PrinterType::kPdf)); printSettings->SetInteger(printing::kSettingDpiHorizontal, printing::kPointsPerInch); printSettings->SetInteger(printing::kSettingDpiVertical, printing::kPointsPerInch); - printSettings->SetInteger(printing::kSettingDuplexMode, printing::SIMPLEX); + printSettings->SetInteger(printing::kSettingDuplexMode, static_cast<int>(printing::mojom::DuplexMode::kSimplex)); printSettings->SetInteger(printing::kSettingCopies, 1); printSettings->SetInteger(printing::kSettingPagesPerSheet, 1); printSettings->SetBoolean(printing::kSettingCollate, false); @@ -164,14 +163,14 @@ static base::DictionaryValue *createPrintSettingsFromQPageLayout(const QPageLayo marginsDict->SetInteger(printing::kSettingMarginRight, pageMarginsInPoints.right()); printSettings->Set(printing::kSettingMarginsCustom, std::move(marginsDict)); - printSettings->SetInteger(printing::kSettingMarginsType, printing::CUSTOM_MARGINS); + printSettings->SetInteger(printing::kSettingMarginsType, (int)printing::mojom::MarginType::kCustomMargins); // pageSizeInMillimeter is in portrait orientation. Transpose it if necessary. printSettings->SetBoolean(printing::kSettingLandscape, pageLayout.orientation() == QPageLayout::Landscape); } else { // QPrinter will handle margins pageSizeInMillimeter = pageLayout.paintRect(QPageLayout::Millimeter); - printSettings->SetInteger(printing::kSettingMarginsType, printing::NO_MARGINS); + printSettings->SetInteger(printing::kSettingMarginsType, (int)printing::mojom::MarginType::kNoMargins); // pageSizeInMillimeter already contains the orientation. printSettings->SetBoolean(printing::kSettingLandscape, false); @@ -216,16 +215,16 @@ void PrintViewManagerQt::PrintToPDFFileWithCallback(const QPageLayout &pageLayou return; if (m_printSettings || !filePath.length()) { - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(callback, false)); + base::PostTask(FROM_HERE, {content::BrowserThread::UI}, + base::BindOnce(callback, false)); return; } m_pdfOutputPath = toFilePath(filePath); m_pdfSaveCallback = callback; if (!PrintToPDFInternal(pageLayout, printInColor)) { - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(callback, false)); + base::PostTask(FROM_HERE, {content::BrowserThread::UI}, + base::BindOnce(callback, false)); resetPdfState(); } } @@ -240,15 +239,15 @@ void PrintViewManagerQt::PrintToPDFWithCallback(const QPageLayout &pageLayout, // If there already is a pending print in progress, don't try starting another one. if (m_printSettings) { - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(callback, QSharedPointer<QByteArray>())); + base::PostTask(FROM_HERE, {content::BrowserThread::UI}, + base::BindOnce(callback, QSharedPointer<QByteArray>())); return; } m_pdfPrintCallback = callback; if (!PrintToPDFInternal(pageLayout, printInColor, useCustomMargins)) { - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(callback, QSharedPointer<QByteArray>())); + base::PostTask(FROM_HERE, {content::BrowserThread::UI}, + base::BindOnce(callback, QSharedPointer<QByteArray>())); resetPdfState(); } @@ -263,34 +262,21 @@ bool PrintViewManagerQt::PrintToPDFInternal(const QPageLayout &pageLayout, m_printSettings.reset(createPrintSettingsFromQPageLayout(pageLayout, useCustomMargins)); m_printSettings->SetBoolean(printing::kSettingShouldPrintBackgrounds, - web_contents()->GetRenderViewHost()-> - GetWebkitPreferences().should_print_backgrounds); + web_contents()->GetOrCreateWebPreferences().should_print_backgrounds); m_printSettings->SetInteger(printing::kSettingColor, - printInColor ? printing::COLOR : printing::GRAYSCALE); + int(printInColor ? printing::mojom::ColorModel::kColor : printing::mojom::ColorModel::kGrayscale)); - if (web_contents()->ShowingInterstitialPage() || web_contents()->IsCrashed()) + if (web_contents()->IsCrashed()) return false; content::RenderFrameHost* rfh = web_contents()->GetMainFrame(); - auto message = std::make_unique<PrintMsg_InitiatePrintPreview>( - rfh->GetRoutingID(), false); + GetPrintRenderFrame(rfh)->InitiatePrintPreview(mojo::PendingAssociatedRemote<printing::mojom::PrintRenderer>(), false); DCHECK(!m_printPreviewRfh); - - if (!rfh->Send(message.release())) { - return false; - } - m_printPreviewRfh = rfh; return true; } -// PrintedPagesSource implementation. -base::string16 PrintViewManagerQt::RenderSourceName() -{ - return base::string16(); -} - PrintViewManagerQt::PrintViewManagerQt(content::WebContents *contents) : PrintViewManagerBaseQt(contents) , m_printPreviewRfh(nullptr) @@ -305,7 +291,6 @@ bool PrintViewManagerQt::OnMessageReceived(const IPC::Message& message, FrameDispatchHelper helper = {this, render_frame_host}; bool handled = true; IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(PrintViewManagerQt, message, render_frame_host); - IPC_MESSAGE_HANDLER(PrintHostMsg_DidShowPrintDialog, OnDidShowPrintDialog) IPC_MESSAGE_HANDLER(PrintHostMsg_RequestPrintPreview, OnRequestPrintPreview) IPC_MESSAGE_HANDLER(PrintHostMsg_MetafileReadyForPrinting, OnMetafileReadyForPrinting); IPC_MESSAGE_HANDLER(PrintHostMsg_DidPreviewPage, OnDidPreviewPage) @@ -324,6 +309,24 @@ void PrintViewManagerQt::RenderFrameDeleted(content::RenderFrameHost *render_fra if (render_frame_host == m_printPreviewRfh) PrintPreviewDone(); PrintViewManagerBaseQt::RenderFrameDeleted(render_frame_host); + m_printRenderFrames.erase(render_frame_host); +} + +const mojo::AssociatedRemote<printing::mojom::PrintRenderFrame> &PrintViewManagerQt::GetPrintRenderFrame(content::RenderFrameHost *rfh) +{ + auto it = m_printRenderFrames.find(rfh); + if (it == m_printRenderFrames.end()) { + mojo::AssociatedRemote<printing::mojom::PrintRenderFrame> remote; + rfh->GetRemoteAssociatedInterfaces()->GetInterface(&remote); + it = m_printRenderFrames.insert(std::make_pair(rfh, std::move(remote))).first; + } else if (it->second.is_bound() && !it->second.is_connected()) { + // When print preview is closed, the remote is disconnected from the + // receiver. Reset and bind the remote before using it again. + it->second.reset(); + rfh->GetRemoteAssociatedInterfaces()->GetInterface(&it->second); + } + + return it->second; } void PrintViewManagerQt::resetPdfState() @@ -337,16 +340,17 @@ void PrintViewManagerQt::resetPdfState() // IPC handlers void PrintViewManagerQt::OnRequestPrintPreview( - const PrintHostMsg_RequestPrintPreview_Params &/*params*/) + const PrintHostMsg_RequestPrintPreview_Params & /*params*/) { - m_printPreviewRfh->Send(new PrintMsg_PrintPreview(m_printPreviewRfh->GetRoutingID(), - *m_printSettings)); + mojo::AssociatedRemote<printing::mojom::PrintRenderFrame> printRenderFrame; + m_printPreviewRfh->GetRemoteAssociatedInterfaces()->GetInterface(&printRenderFrame); + printRenderFrame->PrintPreview(m_printSettings->Clone()); PrintPreviewDone(); } void PrintViewManagerQt::OnMetafileReadyForPrinting(content::RenderFrameHost* rfh, - const PrintHostMsg_DidPreviewDocument_Params& params, - const PrintHostMsg_PreviewIds &ids) + const printing::mojom::DidPreviewDocumentParams& params, + const printing::mojom::PreviewIds &ids) { StopWorker(params.document_cookie); @@ -358,20 +362,16 @@ void PrintViewManagerQt::OnMetafileReadyForPrinting(content::RenderFrameHost* rf resetPdfState(); if (!pdf_print_callback.is_null()) { - QSharedPointer<QByteArray> data_array = GetStdVectorFromHandle(params.content.metafile_data_region); - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(pdf_print_callback, data_array)); + QSharedPointer<QByteArray> data_array = GetStdVectorFromHandle(params.content->metafile_data_region); + base::PostTask(FROM_HERE, {content::BrowserThread::UI}, + base::BindOnce(pdf_print_callback, data_array)); } else { - scoped_refptr<base::RefCountedBytes> data_bytes = GetBytesFromHandle(params.content.metafile_data_region); - base::PostTaskWithTraits(FROM_HERE, {base::MayBlock()}, - base::BindOnce(&SavePdfFile, data_bytes, pdfOutputPath, pdf_save_callback)); + scoped_refptr<base::RefCountedBytes> data_bytes = GetBytesFromHandle(params.content->metafile_data_region); + base::PostTask(FROM_HERE, {base::ThreadPool(), base::MayBlock()}, + base::BindOnce(&SavePdfFile, data_bytes, pdfOutputPath, pdf_save_callback)); } } -void PrintViewManagerQt::OnDidShowPrintDialog() -{ -} - // content::WebContentsObserver implementation. void PrintViewManagerQt::DidStartLoading() { @@ -382,8 +382,8 @@ void PrintViewManagerQt::DidStartLoading() void PrintViewManagerQt::NavigationStopped() { if (!m_pdfPrintCallback.is_null()) { - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(m_pdfPrintCallback, QSharedPointer<QByteArray>())); + base::PostTask(FROM_HERE, {content::BrowserThread::UI}, + base::BindOnce(m_pdfPrintCallback, QSharedPointer<QByteArray>())); } resetPdfState(); PrintViewManagerBaseQt::NavigationStopped(); @@ -393,15 +393,15 @@ void PrintViewManagerQt::RenderProcessGone(base::TerminationStatus status) { PrintViewManagerBaseQt::RenderProcessGone(status); if (!m_pdfPrintCallback.is_null()) { - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(m_pdfPrintCallback, QSharedPointer<QByteArray>())); + base::PostTask(FROM_HERE, {content::BrowserThread::UI}, + base::BindOnce(m_pdfPrintCallback, QSharedPointer<QByteArray>())); } resetPdfState(); } void PrintViewManagerQt::OnDidPreviewPage(content::RenderFrameHost* rfh, - const PrintHostMsg_DidPreviewPage_Params& params, - const PrintHostMsg_PreviewIds& ids) + const printing::mojom::DidPreviewPageParams ¶ms, + const printing::mojom::PreviewIds& ids) { // just consume the message, this is just for sending 'page-preview-ready' for webui } @@ -419,7 +419,7 @@ void PrintViewManagerQt::OnSetupScriptedPrintPreview(content::RenderFrameHost* r return; // close preview - rfh->Send(new PrintMsg_ClosePrintPreviewDialog(rfh->GetRoutingID())); + GetPrintRenderFrame(rfh)->OnPrintPreviewDialogClosed(); client->printRequested(); } @@ -431,8 +431,7 @@ void PrintViewManagerQt::OnShowScriptedPrintPreview(content::RenderFrameHost* rf } void PrintViewManagerQt::PrintPreviewDone() { - m_printPreviewRfh->Send(new PrintMsg_ClosePrintPreviewDialog( - m_printPreviewRfh->GetRoutingID())); + GetPrintRenderFrame(m_printPreviewRfh)->OnPrintPreviewDialogClosed(); m_printPreviewRfh = nullptr; } diff --git a/src/core/printing/print_view_manager_qt.h b/src/core/printing/print_view_manager_qt.h index 14f2688dd..ecb3d6053 100644 --- a/src/core/printing/print_view_manager_qt.h +++ b/src/core/printing/print_view_manager_qt.h @@ -47,32 +47,17 @@ #include "print_view_manager_base_qt.h" #include "qtwebenginecoreglobal_p.h" + #include "base/memory/ref_counted.h" #include "base/strings/string16.h" #include "components/prefs/pref_member.h" -#include "components/printing/browser/print_manager.h" +#include "components/printing/common/print.mojom.h" #include "components/printing/common/print_messages.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" #include "content/public/browser/web_contents_user_data.h" +#include "mojo/public/cpp/bindings/associated_remote.h" #include <QSharedPointer> -struct PrintHostMsg_RequestPrintPreview_Params; -struct PrintHostMsg_DidPreviewDocument_Params; - -namespace content { -class RenderViewHost; -} - -namespace printing { -class JobEventDetails; -class MetafilePlayer; -class PrintJob; -class PrintJobWorkerOwner; -class PrintQueriesQueue; -} - QT_BEGIN_NAMESPACE class QPageLayout; class QString; @@ -98,8 +83,6 @@ public: bool useCustomMargins, const PrintToPDFCallback &callback); - base::string16 RenderSourceName() override; - protected: explicit PrintViewManagerQt(content::WebContents*); @@ -116,22 +99,26 @@ protected: void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override; // IPC handlers - void OnDidShowPrintDialog(); void OnRequestPrintPreview(const PrintHostMsg_RequestPrintPreview_Params&); void OnMetafileReadyForPrinting(content::RenderFrameHost* rfh, - const PrintHostMsg_DidPreviewDocument_Params& params, - const PrintHostMsg_PreviewIds &ids); + const printing::mojom::DidPreviewDocumentParams& params, + const printing::mojom::PreviewIds &ids); void OnSetupScriptedPrintPreview(content::RenderFrameHost* rfh, IPC::Message* reply_msg); void OnDidPreviewPage(content::RenderFrameHost* rfh, - const PrintHostMsg_DidPreviewPage_Params& params, - const PrintHostMsg_PreviewIds& ids); + const printing::mojom::DidPreviewPageParams& params, + const printing::mojom::PreviewIds& ids); void OnShowScriptedPrintPreview(content::RenderFrameHost* rfh, bool source_is_modifiable); bool PrintToPDFInternal(const QPageLayout &, bool printInColor, bool useCustomMargins = true); private: void resetPdfState(); + + // Helper method to fetch the PrintRenderFrame associated remote interface + // pointer. + const mojo::AssociatedRemote<printing::mojom::PrintRenderFrame> &GetPrintRenderFrame(content::RenderFrameHost *rfh); + // content::WebContentsObserver implementation. void DidStartLoading() override; void PrintPreviewDone(); @@ -143,6 +130,9 @@ private: PrintToPDFCallback m_pdfPrintCallback; PrintToPDFFileCallback m_pdfSaveCallback; std::unique_ptr<base::DictionaryValue> m_printSettings; + + std::map<content::RenderFrameHost*,mojo::AssociatedRemote<printing::mojom::PrintRenderFrame>> m_printRenderFrames; + friend class content::WebContentsUserData<PrintViewManagerQt>; DISALLOW_COPY_AND_ASSIGN(PrintViewManagerQt); struct FrameDispatchHelper; diff --git a/src/core/printing/printing_message_filter_qt.cpp b/src/core/printing/printing_message_filter_qt.cpp index 5b9228d20..8d6833dce 100644 --- a/src/core/printing/printing_message_filter_qt.cpp +++ b/src/core/printing/printing_message_filter_qt.cpp @@ -46,20 +46,14 @@ #include "web_engine_context.h" -#include <string> - #include "base/bind.h" #include "chrome/browser/printing/print_job_manager.h" #include "chrome/browser/printing/printer_query.h" #include "components/printing/browser/print_manager_utils.h" #include "components/printing/common/print_messages.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/render_view_host.h" -#include "content/public/browser/web_contents.h" #include "content/public/common/child_process_host.h" -using content::BrowserThread; - namespace QtWebEngineCore { PrintingMessageFilterQt::PrintingMessageFilterQt(int render_process_id) @@ -72,15 +66,14 @@ PrintingMessageFilterQt::PrintingMessageFilterQt(int render_process_id) PrintingMessageFilterQt::~PrintingMessageFilterQt() { } -void PrintingMessageFilterQt::OverrideThreadForMessage( - const IPC::Message& message, BrowserThread::ID* thread) { +void PrintingMessageFilterQt::OnDestruct() const +{ + content::BrowserThread::DeleteOnUIThread::Destruct(this); } bool PrintingMessageFilterQt::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(PrintingMessageFilterQt, message) - IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_GetDefaultPrintSettings, - OnGetDefaultPrintSettings) IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_ScriptedPrint, OnScriptedPrint) IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_UpdatePrintSettings, OnUpdatePrintSettings) @@ -90,57 +83,8 @@ bool PrintingMessageFilterQt::OnMessageReceived(const IPC::Message& message) { return handled; } -void PrintingMessageFilterQt::OnGetDefaultPrintSettings(IPC::Message* reply_msg) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - std::unique_ptr<printing::PrinterQuery> printer_query; - - printer_query = queue_->PopPrinterQuery(0); - if (!printer_query) { - printer_query = - queue_->CreatePrinterQuery(render_process_id_, reply_msg->routing_id()); - } - - // Loads default settings. This is asynchronous, only the IPC message sender - // will hang until the settings are retrieved. - printer_query->GetSettings( - printing::PrinterQuery::GetSettingsAskParam::DEFAULTS, - 0, - false, - printing::DEFAULT_MARGINS, - false, - false, - base::BindOnce(&PrintingMessageFilterQt::OnGetDefaultPrintSettingsReply, - this, - std::move(printer_query), - reply_msg)); -} - -void PrintingMessageFilterQt::OnGetDefaultPrintSettingsReply( - std::unique_ptr<printing::PrinterQuery> printer_query, - IPC::Message* reply_msg) { - PrintMsg_Print_Params params; - if (!printer_query.get() || - printer_query->last_status() != printing::PrintingContext::OK) { - params.Reset(); - } else { - RenderParamsFromPrintSettings(printer_query->settings(), ¶ms); - params.document_cookie = printer_query->cookie(); - } - PrintHostMsg_GetDefaultPrintSettings::WriteReplyParams(reply_msg, params); - Send(reply_msg); - // If printing was enabled. - if (printer_query.get()) { - // If user hasn't cancelled. - if (printer_query->cookie() && printer_query->settings().dpi()) { - queue_->QueuePrinterQuery(std::move(printer_query)); - } else { - printer_query->StopWorker(); - } - } -} - void PrintingMessageFilterQt::OnScriptedPrint( - const PrintHostMsg_ScriptedPrint_Params& params, + const printing::mojom::ScriptedPrintParams& params, IPC::Message* reply_msg) { std::unique_ptr<printing::PrinterQuery> printer_query = queue_->PopPrinterQuery(params.cookie); @@ -164,19 +108,19 @@ void PrintingMessageFilterQt::OnScriptedPrint( void PrintingMessageFilterQt::OnScriptedPrintReply( std::unique_ptr<printing::PrinterQuery> printer_query, IPC::Message* reply_msg) { - PrintMsg_PrintPages_Params params; - + printing::mojom::PrintPagesParams params; + params.params = printing::mojom::PrintParams::New(); if (printer_query->last_status() != printing::PrintingContext::OK || !printer_query->settings().dpi()) { - params.Reset(); + params.params.reset(); } else { - RenderParamsFromPrintSettings(printer_query->settings(), ¶ms.params); - params.params.document_cookie = printer_query->cookie(); + RenderParamsFromPrintSettings(printer_query->settings(), params.params.get()); + params.params->document_cookie = printer_query->cookie(); params.pages = printing::PageRange::GetPages(printer_query->settings().ranges()); } PrintHostMsg_ScriptedPrint::WriteReplyParams(reply_msg, params); Send(reply_msg); - if (!params.params.dpi.IsEmpty() && params.params.document_cookie) { + if (!params.params->dpi.IsEmpty() && params.params->document_cookie) { queue_->QueuePrinterQuery(std::move(printer_query)); } else { printer_query->StopWorker(); @@ -186,13 +130,21 @@ void PrintingMessageFilterQt::OnScriptedPrintReply( void PrintingMessageFilterQt::OnUpdatePrintSettings(int document_cookie, base::Value job_settings, IPC::Message* reply_msg) { - std::unique_ptr<printing::PrinterQuery> printer_query; - printer_query = queue_->PopPrinterQuery(document_cookie); + if (!job_settings.is_dict() || + !job_settings.FindIntKey(printing::kSettingPrinterType)) { + // Reply with null query. + OnUpdatePrintSettingsReply(nullptr, reply_msg); + return; + } + + std::unique_ptr<printing::PrinterQuery> printer_query = + queue_->PopPrinterQuery(document_cookie); if (!printer_query.get()) { printer_query = queue_->CreatePrinterQuery( content::ChildProcessHost::kInvalidUniqueID, MSG_ROUTING_NONE); } - printer_query->SetSettings( + auto* printer_query_ptr = printer_query.get(); + printer_query_ptr->SetSettings( std::move(job_settings), base::BindOnce(&PrintingMessageFilterQt::OnUpdatePrintSettingsReply, this, std::move(printer_query), reply_msg)); @@ -200,13 +152,14 @@ void PrintingMessageFilterQt::OnUpdatePrintSettings(int document_cookie, void PrintingMessageFilterQt::OnUpdatePrintSettingsReply(std::unique_ptr<printing::PrinterQuery> printer_query, IPC::Message* reply_msg) { - PrintMsg_PrintPages_Params params; + printing::mojom::PrintPagesParams params; + params.params = printing::mojom::PrintParams::New(); if (!printer_query.get() || printer_query->last_status() != printing::PrintingContext::OK) { - params.Reset(); + params.params.reset(); } else { - RenderParamsFromPrintSettings(printer_query->settings(), ¶ms.params); - params.params.document_cookie = printer_query->cookie(); + RenderParamsFromPrintSettings(printer_query->settings(), params.params.get()); + params.params->document_cookie = printer_query->cookie(); params.pages = printing::PageRange::GetPages(printer_query->settings().ranges()); } @@ -226,7 +179,7 @@ void PrintingMessageFilterQt::OnUpdatePrintSettingsReply(std::unique_ptr<printin } } -void PrintingMessageFilterQt::OnCheckForCancel(const PrintHostMsg_PreviewIds& ids, +void PrintingMessageFilterQt::OnCheckForCancel(const printing::mojom::PreviewIds& ids, bool* cancel) { *cancel = false; } diff --git a/src/core/printing/printing_message_filter_qt.h b/src/core/printing/printing_message_filter_qt.h index 88559d3df..3a449af70 100644 --- a/src/core/printing/printing_message_filter_qt.h +++ b/src/core/printing/printing_message_filter_qt.h @@ -46,28 +46,13 @@ #include <string> -#include "base/compiler_specific.h" -#include "components/prefs/pref_member.h" #include "content/public/browser/browser_message_filter.h" -#if defined(OS_WIN) -#include "base/memory/shared_memory.h" -#endif - -struct PrintHostMsg_PreviewIds; -struct PrintHostMsg_ScriptedPrint_Params; - -namespace base { -class DictionaryValue; -class FilePath; -} - -namespace content { -class WebContents; -} - namespace printing { -class PrintJobManager; +namespace mojom { +class ScriptedPrintParams; +class PreviewIds; +} class PrintQueriesQueue; class PrinterQuery; } @@ -80,28 +65,20 @@ class PrintingMessageFilterQt : public content::BrowserMessageFilter { PrintingMessageFilterQt(int render_process_id); // content::BrowserMessageFilter methods. - void OverrideThreadForMessage(const IPC::Message& message, - content::BrowserThread::ID* thread) override; bool OnMessageReceived(const IPC::Message& message) override; private: - ~PrintingMessageFilterQt() override; + friend class base::DeleteHelper<PrintingMessageFilterQt>; + friend class content::BrowserThread; - // GetPrintSettingsForRenderView must be called via PostTask and - // base::Bind. Collapse the settings-specific params into a - // struct to avoid running into issues with too many params - // to base::Bind. - struct GetPrintSettingsForRenderViewParams; + ~PrintingMessageFilterQt() override; - // Get the default print setting. - void OnGetDefaultPrintSettings(IPC::Message* reply_msg); - void OnGetDefaultPrintSettingsReply(std::unique_ptr<printing::PrinterQuery> printer_query, - IPC::Message* reply_msg); + void OnDestruct() const override; // The renderer host have to show to the user the print dialog and returns // the selected print settings. The task is handled by the print worker // thread and the UI thread. The reply occurs on the IO thread. - void OnScriptedPrint(const PrintHostMsg_ScriptedPrint_Params& params, + void OnScriptedPrint(const printing::mojom::ScriptedPrintParams& params, IPC::Message* reply_msg); void OnScriptedPrintReply(std::unique_ptr<printing::PrinterQuery> printer_query, IPC::Message* reply_msg); @@ -116,7 +93,7 @@ class PrintingMessageFilterQt : public content::BrowserMessageFilter { IPC::Message* reply_msg); // Check to see if print preview has been cancelled. - void OnCheckForCancel(const PrintHostMsg_PreviewIds& ids, bool* cancel); + void OnCheckForCancel(const printing::mojom::PreviewIds& ids, bool* cancel); const int render_process_id_; diff --git a/src/core/process_main.cpp b/src/core/process_main.cpp index d661d3b90..827e31037 100644 --- a/src/core/process_main.cpp +++ b/src/core/process_main.cpp @@ -44,38 +44,45 @@ #if defined(OS_WIN) #include "sandbox/win/src/sandbox_types.h" #include "content/public/app/sandbox_helper_win.h" -#elif defined(OS_MACOSX) +#elif defined(OS_MAC) #include "base/logging.h" #include "sandbox/mac/seatbelt_exec.h" #endif -namespace QtWebEngine { +namespace QtWebEngineCore { + +#if defined(OS_WIN) +extern sandbox::SandboxInterfaceInfo *staticSandboxInterfaceInfo(sandbox::SandboxInterfaceInfo *info = nullptr); +#endif /*! \internal */ int processMain(int argc, const char **argv) { - QtWebEngineCore::ContentMainDelegateQt delegate; + ContentMainDelegateQt delegate; content::ContentMainParams params(&delegate); #if defined(OS_WIN) HINSTANCE instance_handle = NULL; + params.sandbox_info = staticSandboxInterfaceInfo(); sandbox::SandboxInterfaceInfo sandbox_info = {0}; - content::InitializeSandboxInfo(&sandbox_info); + if (!params.sandbox_info) { + content::InitializeSandboxInfo(&sandbox_info); + params.sandbox_info = &sandbox_info; + } params.instance = instance_handle; - params.sandbox_info = &sandbox_info; #else params.argc = argc; params.argv = argv; #endif // OS_WIN -#if defined(OS_MACOSX) +#if defined(OS_MAC) sandbox::SeatbeltExecServer::CreateFromArgumentsResult seatbelt = sandbox::SeatbeltExecServer::CreateFromArguments(argv[0], argc, const_cast<char**>(argv)); if (seatbelt.sandbox_required) { CHECK(seatbelt.server->InitializeSandbox()); } -#endif // defined(OS_MACOSX) +#endif // defined(OS_MAC) return content::ContentMain(params); } -} // namespace +} // namespace QtWebEngineCore diff --git a/src/core/process_main.h b/src/core/process_main.h index 00c029d9f..fed2f3064 100644 --- a/src/core/process_main.h +++ b/src/core/process_main.h @@ -50,7 +50,7 @@ #include <QtWebEngineCore/private/qtwebenginecoreglobal_p.h> -namespace QtWebEngine { +namespace QtWebEngineCore { Q_WEBENGINECORE_PRIVATE_EXPORT int processMain(int argc, const char **argv); diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp index ba2f97475..4dab8aa34 100644 --- a/src/core/profile_adapter.cpp +++ b/src/core/profile_adapter.cpp @@ -43,13 +43,17 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/browsing_data_remover.h" #include "content/public/browser/download_manager.h" +#include "content/public/browser/shared_cors_origin_access_list.h" +#include "content/public/browser/storage_partition.h" +#include "services/network/public/cpp/cors/origin_access_list.h" +#include "url/url_util.h" #include "api/qwebengineurlscheme.h" #include "content_browser_client_qt.h" #include "download_manager_delegate_qt.h" -#include "net/url_request_context_getter_qt.h" #include "permission_manager_qt.h" #include "profile_adapter_client.h" +#include "profile_io_data_qt.h" #include "profile_qt.h" #include "renderer_host/user_resource_controller_host.h" #include "type_conversion.h" @@ -83,6 +87,9 @@ inline QString buildLocationFromStandardPath(const QString &standardPath, const namespace QtWebEngineCore { +// static +QPointer<ProfileAdapter> ProfileAdapter::s_profileForGlobalCertificateVerification; + ProfileAdapter::ProfileAdapter(const QString &storageName): m_name(storageName) , m_offTheRecord(storageName.isEmpty()) @@ -91,12 +98,10 @@ ProfileAdapter::ProfileAdapter(const QString &storageName): , m_persistentCookiesPolicy(AllowPersistentCookies) , m_visitedLinksPolicy(TrackVisitedLinksOnDisk) , m_httpCacheMaxSize(0) - , m_pageRequestInterceptors(0) { WebEngineContext::current()->addProfileAdapter(this); // creation of profile requires webengine context m_profile.reset(new ProfileQt(this)); - content::BrowserContext::Initialize(m_profile.data(), toFilePath(dataPath())); // fixme: this should not be here m_profile->m_profileIOData->initializeOnUIThread(); m_customUrlSchemeHandlers.insert(QByteArrayLiteral("qrc"), &m_qrcHandler); @@ -104,10 +109,22 @@ ProfileAdapter::ProfileAdapter(const QString &storageName): if (!storageName.isEmpty()) extensions::ExtensionSystem::Get(m_profile.data())->InitForRegularProfile(true); #endif + + // Allow XMLHttpRequests from qrc to file. + // ### consider removing for Qt6 + url::Origin qrc = url::Origin::Create(GURL("qrc://")); + auto pattern = network::mojom::CorsOriginPattern::New("file", "", 0, + network::mojom::CorsDomainMatchMode::kAllowSubdomains, + network::mojom::CorsPortMatchMode::kAllowAnyPort, + network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority); + std::vector<network::mojom::CorsOriginPatternPtr> list; + list.push_back(std::move(pattern)); + m_profile->GetSharedCorsOriginAccessList()->SetForOrigin(qrc, std::move(list), {}, base::BindOnce([]{})); } ProfileAdapter::~ProfileAdapter() { + content::BrowserContext::NotifyWillBeDestroyed(m_profile.data()); while (!m_webContentsAdapterClients.isEmpty()) { m_webContentsAdapterClients.first()->releaseProfile(); } @@ -118,8 +135,9 @@ ProfileAdapter::~ProfileAdapter() } #if QT_CONFIG(ssl) delete m_clientCertificateStore; + m_clientCertificateStore = nullptr; #endif - Q_ASSERT(m_pageRequestInterceptors == 0); + WebEngineContext::flushMessages(); } void ProfileAdapter::setStorageName(const QString &storageName) @@ -129,8 +147,8 @@ void ProfileAdapter::setStorageName(const QString &storageName) m_name = storageName; if (!m_offTheRecord) { m_profile->setupPrefService(); - if (m_profile->m_urlRequestContextGetter.get()) - m_profile->m_profileIOData->updateStorageSettings(); + if (!m_profile->m_profileIOData->isClearHttpCacheInProgress()) + m_profile->m_profileIOData->resetNetworkContext(); if (m_visitedLinksManager) resetVisitedLinksManager(); } @@ -142,8 +160,8 @@ void ProfileAdapter::setOffTheRecord(bool offTheRecord) return; m_offTheRecord = offTheRecord; m_profile->setupPrefService(); - if (m_profile->m_urlRequestContextGetter.get()) - m_profile->m_profileIOData->updateStorageSettings(); + if (!m_profile->m_profileIOData->isClearHttpCacheInProgress()) + m_profile->m_profileIOData->resetNetworkContext(); if (m_visitedLinksManager) resetVisitedLinksManager(); } @@ -181,19 +199,7 @@ QWebEngineUrlRequestInterceptor *ProfileAdapter::requestInterceptor() void ProfileAdapter::setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor) { - if (m_requestInterceptor == interceptor) - return; - - if (m_requestInterceptor) - disconnect(m_requestInterceptor, &QObject::destroyed, this, nullptr); m_requestInterceptor = interceptor; - if (m_requestInterceptor) - connect(m_requestInterceptor, &QObject::destroyed, this, [this] () { - m_profile->m_profileIOData->updateRequestInterceptor(); - Q_ASSERT(!m_profile->m_profileIOData->requestInterceptor()); - }); - - m_profile->m_profileIOData->updateRequestInterceptor(); } void ProfileAdapter::addClient(ProfileAdapterClient *adapterClient) @@ -206,20 +212,6 @@ void ProfileAdapter::removeClient(ProfileAdapterClient *adapterClient) m_clients.removeOne(adapterClient); } -void ProfileAdapter::addPageRequestInterceptor() -{ - ++m_pageRequestInterceptors; - m_profile->m_profileIOData->updateRequestInterceptor(); -} - -void ProfileAdapter::removePageRequestInterceptor() -{ - Q_ASSERT(m_pageRequestInterceptors > 0); - --m_pageRequestInterceptors; - m_profile->m_profileIOData->updateRequestInterceptor(); -} - - void ProfileAdapter::cancelDownload(quint32 downloadId) { downloadManagerDelegate()->cancelDownload(downloadId); @@ -258,13 +250,17 @@ QObject* ProfileAdapter::globalQObjectRoot() QString ProfileAdapter::dataPath() const { - if (m_offTheRecord) - return QString(); if (!m_dataPath.isEmpty()) return m_dataPath; - if (!m_name.isNull()) - return buildLocationFromStandardPath(QStandardPaths::writableLocation(QStandardPaths::DataLocation), m_name); - return QString(); + // And off-the-record or memory-only profile should not write to disk + // but Chromium often creates temporary directories anyway, so given them + // a location to do so. + QString name = m_name; + if (m_offTheRecord) + name = QStringLiteral("OffTheRecord"); + else if (m_name.isEmpty()) + name = QStringLiteral("UnknownProfile"); + return buildLocationFromStandardPath(QStandardPaths::writableLocation(QStandardPaths::DataLocation), name); } void ProfileAdapter::setDataPath(const QString &path) @@ -272,13 +268,11 @@ void ProfileAdapter::setDataPath(const QString &path) if (m_dataPath == path) return; m_dataPath = path; - if (!m_offTheRecord) { - m_profile->setupPrefService(); - if (m_profile->m_urlRequestContextGetter.get()) - m_profile->m_profileIOData->updateStorageSettings(); - if (m_visitedLinksManager) - resetVisitedLinksManager(); - } + m_profile->setupPrefService(); + if (!m_profile->m_profileIOData->isClearHttpCacheInProgress()) + m_profile->m_profileIOData->resetNetworkContext(); + if (!m_offTheRecord && m_visitedLinksManager) + resetVisitedLinksManager(); } void ProfileAdapter::setDownloadPath(const QString &path) @@ -302,23 +296,8 @@ void ProfileAdapter::setCachePath(const QString &path) if (m_cachePath == path) return; m_cachePath = path; - if (!m_offTheRecord && m_profile->m_urlRequestContextGetter.get()) - m_profile->m_profileIOData->updateHttpCache(); -} - -QString ProfileAdapter::cookiesPath() const -{ - if (m_offTheRecord) - return QString(); - QString basePath = dataPath(); - if (!basePath.isEmpty()) { - // This is a typo fix. We still need the old path in order to avoid breaking migration. - QDir coookiesFolder(basePath % QLatin1String("/Coookies")); - if (coookiesFolder.exists()) - return coookiesFolder.path(); - return basePath % QLatin1String("/Cookies"); - } - return QString(); + if (!m_offTheRecord && !m_profile->m_profileIOData->isClearHttpCacheInProgress()) + m_profile->m_profileIOData->resetNetworkContext(); } QString ProfileAdapter::httpCachePath() const @@ -340,17 +319,21 @@ QString ProfileAdapter::httpUserAgent() const void ProfileAdapter::setHttpUserAgent(const QString &userAgent) { - if (m_httpUserAgent == userAgent) + const QString httpUserAgent = userAgent.simplified(); + if (m_httpUserAgent == httpUserAgent) return; - m_httpUserAgent = userAgent.simplified(); + m_httpUserAgent = httpUserAgent; + const std::string stdUserAgent = httpUserAgent.toStdString(); std::vector<content::WebContentsImpl *> list = content::WebContentsImpl::GetAllWebContents(); for (content::WebContentsImpl *web_contents : list) if (web_contents->GetBrowserContext() == m_profile.data()) - web_contents->SetUserAgentOverride(m_httpUserAgent.toStdString(), true); + web_contents->SetUserAgentOverride(blink::UserAgentOverride::UserAgentOnly(stdUserAgent), true); - if (m_profile->m_urlRequestContextGetter.get()) - m_profile->m_profileIOData->updateUserAgent(); + content::BrowserContext::ForEachStoragePartition( + m_profile.get(), base::BindRepeating([](const std::string &user_agent, content::StoragePartition *storage_partition) { + storage_partition->GetNetworkContext()->SetUserAgent(user_agent); + }, stdUserAgent)); } ProfileAdapter::HttpCacheType ProfileAdapter::httpCacheType() const @@ -368,13 +351,16 @@ void ProfileAdapter::setHttpCacheType(ProfileAdapter::HttpCacheType newhttpCache m_httpCacheType = newhttpCacheType; if (oldCacheType == httpCacheType()) return; - if (!m_offTheRecord && m_profile->m_urlRequestContextGetter.get()) - m_profile->m_profileIOData->updateHttpCache(); + if (!m_offTheRecord && !m_profile->m_profileIOData->isClearHttpCacheInProgress()) { + m_profile->m_profileIOData->resetNetworkContext(); + if (m_httpCacheType == NoCache) + clearHttpCache(); + } } ProfileAdapter::PersistentCookiesPolicy ProfileAdapter::persistentCookiesPolicy() const { - if (isOffTheRecord() || cookiesPath().isEmpty()) + if (isOffTheRecord() || m_name.isEmpty()) return NoPersistentCookies; return m_persistentCookiesPolicy; } @@ -385,15 +371,15 @@ void ProfileAdapter::setPersistentCookiesPolicy(ProfileAdapter::PersistentCookie m_persistentCookiesPolicy = newPersistentCookiesPolicy; if (oldPolicy == persistentCookiesPolicy()) return; - if (!m_offTheRecord && m_profile->m_urlRequestContextGetter.get()) - m_profile->m_profileIOData->updateCookieStore(); + if (!m_offTheRecord && !m_profile->m_profileIOData->isClearHttpCacheInProgress()) + m_profile->m_profileIOData->resetNetworkContext(); } ProfileAdapter::VisitedLinksPolicy ProfileAdapter::visitedLinksPolicy() const { if (isOffTheRecord() || m_visitedLinksPolicy == DoNotTrackVisitedLinks) return DoNotTrackVisitedLinks; - if (dataPath().isEmpty()) + if (m_name.isEmpty()) return TrackVisitedLinksInMemory; return m_visitedLinksPolicy; } @@ -440,8 +426,8 @@ void ProfileAdapter::setHttpCacheMaxSize(int maxSize) if (m_httpCacheMaxSize == maxSize) return; m_httpCacheMaxSize = maxSize; - if (!m_offTheRecord && m_profile->m_urlRequestContextGetter.get()) - m_profile->m_profileIOData->updateHttpCache(); + if (!m_offTheRecord && !m_profile->m_profileIOData->isClearHttpCacheInProgress()) + m_profile->m_profileIOData->resetNetworkContext(); } enum class SchemeType { Protected, Overridable, Custom, Unknown }; @@ -486,8 +472,10 @@ const QList<QByteArray> ProfileAdapter::customUrlSchemes() const void ProfileAdapter::updateCustomUrlSchemeHandlers() { - if (m_profile->m_urlRequestContextGetter.get()) - m_profile->m_profileIOData->updateJobFactory(); + content::BrowserContext::ForEachStoragePartition( + m_profile.get(), base::BindRepeating([](content::StoragePartition *storage_partition) { + storage_partition->ResetURLLoaderFactories(); + })); } void ProfileAdapter::removeUrlSchemeHandler(QWebEngineUrlSchemeHandler *handler) @@ -548,9 +536,11 @@ void ProfileAdapter::installUrlSchemeHandler(const QByteArray &scheme, QWebEngin void ProfileAdapter::removeAllUrlSchemeHandlers() { - m_customUrlSchemeHandlers.clear(); - m_customUrlSchemeHandlers.insert(QByteArrayLiteral("qrc"), &m_qrcHandler); - updateCustomUrlSchemeHandlers(); + if (m_customUrlSchemeHandlers.size() > 1) { + m_customUrlSchemeHandlers.clear(); + m_customUrlSchemeHandlers.insert(QByteArrayLiteral("qrc"), &m_qrcHandler); + updateCustomUrlSchemeHandlers(); + } } UserResourceControllerHost *ProfileAdapter::userResourceController() @@ -560,7 +550,7 @@ UserResourceControllerHost *ProfileAdapter::userResourceController() return m_userResourceController.data(); } -void ProfileAdapter::permissionRequestReply(const QUrl &origin, PermissionType type, bool reply) +void ProfileAdapter::permissionRequestReply(const QUrl &origin, PermissionType type, PermissionState reply) { static_cast<PermissionManagerQt*>(profile()->GetPermissionControllerDelegate())->permissionRequestReply(origin, type, reply); } @@ -593,25 +583,26 @@ void ProfileAdapter::setHttpAcceptLanguage(const QString &httpAcceptLanguage) return; m_httpAcceptLanguage = httpAcceptLanguage; + std::string http_accept_language = httpAcceptLanguageWithoutQualities().toStdString(); + std::vector<content::WebContentsImpl *> list = content::WebContentsImpl::GetAllWebContents(); for (content::WebContentsImpl *web_contents : list) { if (web_contents->GetBrowserContext() == m_profile.data()) { blink::mojom::RendererPreferences *rendererPrefs = web_contents->GetMutableRendererPrefs(); - rendererPrefs->accept_languages = httpAcceptLanguageWithoutQualities().toStdString(); - web_contents->GetRenderViewHost()->SyncRendererPrefs(); + rendererPrefs->accept_languages = http_accept_language; + web_contents->SyncRendererPrefs(); } } - if (m_profile->m_urlRequestContextGetter.get()) - m_profile->m_profileIOData->updateUserAgent(); + content::BrowserContext::ForEachStoragePartition( + m_profile.get(), base::BindRepeating([](std::string accept_language, content::StoragePartition *storage_partition) { + storage_partition->GetNetworkContext()->SetAcceptLanguage(accept_language); + }, http_accept_language)); } void ProfileAdapter::clearHttpCache() { - content::BrowsingDataRemover *remover = content::BrowserContext::GetBrowsingDataRemover(m_profile.data()); - remover->Remove(base::Time(), base::Time::Max(), - content::BrowsingDataRemover::DATA_TYPE_CACHE, - content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB | content::BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB); + m_profile->m_profileIOData->clearHttpCache(); } void ProfileAdapter::setSpellCheckLanguages(const QStringList &languages) @@ -666,24 +657,26 @@ void ProfileAdapter::setUseForGlobalCertificateVerification(bool enable) if (m_usedForGlobalCertificateVerification == enable) return; - static QPointer<ProfileAdapter> profileForglobalCertificateVerification; - m_usedForGlobalCertificateVerification = enable; if (enable) { - if (profileForglobalCertificateVerification) { - profileForglobalCertificateVerification->m_usedForGlobalCertificateVerification = false; - for (auto *client : qAsConst(profileForglobalCertificateVerification->m_clients)) + if (s_profileForGlobalCertificateVerification) { + s_profileForGlobalCertificateVerification->m_usedForGlobalCertificateVerification = false; + for (auto *client : qAsConst(s_profileForGlobalCertificateVerification->m_clients)) client->useForGlobalCertificateVerificationChanged(); + } else { + // OCSP enabled + for (auto adapter : qAsConst(WebEngineContext::current()->m_profileAdapters)) + adapter->m_profile->m_profileIOData->resetNetworkContext(); } - profileForglobalCertificateVerification = this; + s_profileForGlobalCertificateVerification = this; } else { - Q_ASSERT(profileForglobalCertificateVerification); - Q_ASSERT(profileForglobalCertificateVerification == this); - profileForglobalCertificateVerification = nullptr; + Q_ASSERT(s_profileForGlobalCertificateVerification); + Q_ASSERT(s_profileForGlobalCertificateVerification == this); + s_profileForGlobalCertificateVerification = nullptr; + // OCSP disabled + for (auto adapter : qAsConst(WebEngineContext::current()->m_profileAdapters)) + adapter->m_profile->m_profileIOData->resetNetworkContext(); } - - if (m_profile->m_urlRequestContextGetter.get()) - m_profile->m_profileIOData->updateUsedForGlobalCertificateVerification(); } bool ProfileAdapter::isUsedForGlobalCertificateVerification() const @@ -697,7 +690,7 @@ QString ProfileAdapter::determineDownloadPath(const QString &downloadDirectory, QString suggestedFilePath = suggestedFile.absoluteFilePath(); base::FilePath tmpFilePath(toFilePath(suggestedFilePath).NormalizePathSeparatorsTo('/')); - int uniquifier = base::GetUniquePathNumber(tmpFilePath, base::FilePath::StringType()); + int uniquifier = base::GetUniquePathNumber(tmpFilePath); if (uniquifier > 0) suggestedFilePath = toQt(tmpFilePath.InsertBeforeExtensionASCII(base::StringPrintf(" (%d)", uniquifier)).AsUTF8Unsafe()); else if (uniquifier == -1) { diff --git a/src/core/profile_adapter.h b/src/core/profile_adapter.h index 1b89a8004..caeff246a 100644 --- a/src/core/profile_adapter.h +++ b/src/core/profile_adapter.h @@ -123,7 +123,6 @@ public: void setCachePath(const QString &path); QString httpCachePath() const; - QString cookiesPath() const; QString httpUserAgent() const; void setHttpUserAgent(const QString &userAgent); @@ -165,6 +164,12 @@ public: ClipboardWrite = 6, }; + enum PermissionState { + AskPermission = 0, + AllowedPermission = 1, + DeniedPermission = 2 + }; + HttpCacheType httpCacheType() const; void setHttpCacheType(ProfileAdapter::HttpCacheType); @@ -188,7 +193,7 @@ public: const QList<QByteArray> customUrlSchemes() const; UserResourceControllerHost *userResourceController(); - void permissionRequestReply(const QUrl &origin, PermissionType type, bool reply); + void permissionRequestReply(const QUrl &origin, PermissionType type, PermissionState reply); bool checkPermission(const QUrl &origin, PermissionType type); QString httpAcceptLanguageWithoutQualities() const; @@ -200,10 +205,6 @@ public: void setUseForGlobalCertificateVerification(bool enable = true); bool isUsedForGlobalCertificateVerification() const; - void addPageRequestInterceptor(); - void removePageRequestInterceptor(); - bool hasPageRequestInterceptor() const { return m_pageRequestInterceptors > 0; } - #if QT_CONFIG(ssl) QWebEngineClientCertificateStore *clientCertificateStore(); #endif @@ -215,6 +216,7 @@ public: QString determineDownloadPath(const QString &downloadDirectory, const QString &suggestedFilename, const time_t &startTime); + static QPointer<ProfileAdapter> s_profileForGlobalCertificateVerification; private: void updateCustomUrlSchemeHandlers(); void resetVisitedLinksManager(); @@ -248,7 +250,6 @@ private: QList<ProfileAdapterClient*> m_clients; QVector<WebContentsAdapterClient *> m_webContentsAdapterClients; int m_httpCacheMaxSize; - int m_pageRequestInterceptors; QrcUrlSchemeHandler m_qrcHandler; Q_DISABLE_COPY(ProfileAdapter) diff --git a/src/core/profile_io_data_qt.cpp b/src/core/profile_io_data_qt.cpp index 2d0481978..8e6c8fed3 100644 --- a/src/core/profile_io_data_qt.cpp +++ b/src/core/profile_io_data_qt.cpp @@ -40,137 +40,28 @@ #include "profile_io_data_qt.h" #include "base/task/post_task.h" -#include "chrome/common/chrome_constants.h" -#include "components/certificate_transparency/ct_known_logs.h" -#include "components/network_session_configurator/common/network_features.h" +#include "content/browser/storage_partition_impl.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/browsing_data_remover.h" -#include "content/public/browser/cookie_store_factory.h" #include "content/public/browser/shared_cors_origin_access_list.h" #include "content/public/common/content_features.h" -#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h" -#include "chrome/browser/net/chrome_mojo_proxy_resolver_factory.h" -#include "chrome/common/chrome_switches.h" -#include "components/proxy_config/pref_proxy_config_tracker_impl.h" -#include "net/cert/cert_verifier.h" -#include "net/cert/ct_log_verifier.h" -#include "net/cert/ct_policy_enforcer.h" -#include "net/cert/multi_log_ct_verifier.h" -#include "net/cert_net/cert_net_fetcher_impl.h" -#include "net/ftp/ftp_auth_cache.h" -#include "net/dns/host_resolver_manager.h" -#include "net/http/http_auth_handler_factory.h" -#include "net/http/http_auth_scheme.h" -#include "net/http/http_auth_preferences.h" -#include "net/http/http_cache.h" -#include "net/http/http_server_properties_impl.h" -#include "net/http/http_network_session.h" -#include "net/http/transport_security_persister.h" -#include "net/proxy_resolution/dhcp_pac_file_fetcher_factory.h" -#include "net/proxy_resolution/pac_file_fetcher_impl.h" -#include "net/proxy_resolution/proxy_config_service.h" -#include "net/proxy_resolution/proxy_resolution_service.h" #include "net/ssl/ssl_config_service_defaults.h" -#include "net/url_request/data_protocol_handler.h" -#include "net/url_request/file_protocol_handler.h" -#include "net/url_request/ftp_protocol_handler.h" -#include "net/url_request/static_http_user_agent_settings.h" -#include "net/url_request/url_request_context_storage.h" -#include "net/url_request/url_request_job_factory_impl.h" -#include "net/url_request/url_request_intercepting_job_factory.h" -#include "services/file/user_id_map.h" -#include "services/network/proxy_service_mojo.h" -#include "services/network/restricted_cookie_manager.h" -#include "services/network/public/cpp/features.h" #include "services/network/public/cpp/cors/origin_access_list.h" #include "net/client_cert_override.h" #include "net/client_cert_store_data.h" #include "net/cookie_monster_delegate_qt.h" -#include "net/custom_protocol_handler.h" -#include "net/network_delegate_qt.h" -#include "net/proxy_config_service_qt.h" -#include "net/restricted_cookie_manager_qt.h" #include "net/system_network_context_manager.h" -#include "net/url_request_context_getter_qt.h" #include "profile_qt.h" #include "resource_context_qt.h" #include "type_conversion.h" -#if defined(USE_NSS_CERTS) -#include "net/cert_net/nss_ocsp.h" -#endif - -#if defined(OS_LINUX) || defined(OS_MACOSX) -#include "net/cert/cert_net_fetcher.h" -#include "net/cert_net/cert_net_fetcher_impl.h" -#endif - +#include <QDebug> #include <mutex> -#include <QVariant> namespace QtWebEngineCore { -static scoped_refptr<net::CertNetFetcherImpl> s_certNetFetcher; - -static bool doNetworkSessionParamsMatch(const net::HttpNetworkSession::Params &first, - const net::HttpNetworkSession::Params &second) -{ - if (first.ignore_certificate_errors != second.ignore_certificate_errors) - return false; - return true; -} - -static bool doNetworkSessionContextMatch(const net::HttpNetworkSession::Context &first, - const net::HttpNetworkSession::Context &second) -{ - if (first.transport_security_state != second.transport_security_state) - return false; - if (first.cert_verifier != second.cert_verifier) - return false; - if (first.proxy_resolution_service != second.proxy_resolution_service) - return false; - if (first.ssl_config_service != second.ssl_config_service) - return false; - if (first.http_auth_handler_factory != second.http_auth_handler_factory) - return false; - if (first.http_user_agent_settings != second.http_user_agent_settings) - return false; - if (first.http_server_properties != second.http_server_properties) - return false; - if (first.host_resolver != second.host_resolver) - return false; - if (first.cert_transparency_verifier != second.cert_transparency_verifier) - return false; - if (first.ct_policy_enforcer != second.ct_policy_enforcer) - return false; - return true; -} - -static net::HttpNetworkSession::Context generateNetworkSessionContext(net::URLRequestContext *urlRequestContext) -{ - net::HttpNetworkSession::Context network_session_context; - network_session_context.transport_security_state = urlRequestContext->transport_security_state(); - network_session_context.cert_verifier = urlRequestContext->cert_verifier(); - network_session_context.proxy_resolution_service = urlRequestContext->proxy_resolution_service(); - network_session_context.ssl_config_service = urlRequestContext->ssl_config_service(); - network_session_context.http_auth_handler_factory = urlRequestContext->http_auth_handler_factory(); - network_session_context.http_user_agent_settings = urlRequestContext->http_user_agent_settings(); - network_session_context.http_server_properties = urlRequestContext->http_server_properties(); - network_session_context.host_resolver = urlRequestContext->host_resolver(); - network_session_context.cert_transparency_verifier = urlRequestContext->cert_transparency_verifier(); - network_session_context.ct_policy_enforcer = urlRequestContext->ct_policy_enforcer(); - return network_session_context; -} - -static net::HttpNetworkSession::Params generateNetworkSessionParams(bool ignoreCertificateErrors) -{ - net::HttpNetworkSession::Params network_session_params; - network_session_params.ignore_certificate_errors = ignoreCertificateErrors; - return network_session_params; -} - ProfileIODataQt::ProfileIODataQt(ProfileQt *profile) : m_profile(profile), #if QT_CONFIG(ssl) @@ -188,28 +79,7 @@ ProfileIODataQt::~ProfileIODataQt() if (content::BrowserThread::IsThreadInitialized(content::BrowserThread::IO)) DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (m_useForGlobalCertificateVerification) { -#if defined(USE_NSS_CERTS) - net::SetURLRequestContextForNSSHttpIO(nullptr); -#endif - if (s_certNetFetcher) { - s_certNetFetcher->Shutdown(); - s_certNetFetcher.reset(); - } - } - - if (m_urlRequestContext) { - if (m_urlRequestContext->proxy_resolution_service()) - m_urlRequestContext->proxy_resolution_service()->OnShutdown(); - m_restrictedCookieManagerBindings.CloseAllBindings(); - cancelAllUrlRequests(); - } - m_resourceContext.reset(); - if (m_cookieDelegate) - m_cookieDelegate->setCookieMonster(0); // this will let CookieMonsterDelegateQt be deleted - m_networkDelegate.reset(); - delete m_proxyConfigService.fetchAndStoreAcquire(0); } QPointer<ProfileAdapter> ProfileIODataQt::profileAdapter() @@ -234,14 +104,6 @@ void ProfileIODataQt::shutdownOnUIThread() } } -net::URLRequestContext *ProfileIODataQt::urlRequestContext() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (!m_initialized) - initializeOnIOThread(); - return m_urlRequestContext.get(); -} - content::ResourceContext *ProfileIODataQt::resourceContext() { return m_resourceContext.get(); @@ -254,551 +116,82 @@ extensions::ExtensionSystemQt* ProfileIODataQt::GetExtensionSystem() } #endif // BUILDFLAG(ENABLE_EXTENSIONS) -base::WeakPtr<ProfileIODataQt> ProfileIODataQt::getWeakPtrOnUIThread() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK(m_initialized); - return m_weakPtr; -} - base::WeakPtr<ProfileIODataQt> ProfileIODataQt::getWeakPtrOnIOThread() { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); return m_weakPtrFactory.GetWeakPtr(); } -void ProfileIODataQt::initializeOnIOThread() -{ - m_networkDelegate.reset(new NetworkDelegateQt(this)); - m_hostResolver = net::HostResolver::CreateStandaloneResolver(nullptr); - m_urlRequestContext.reset(new net::URLRequestContext()); - m_urlRequestContext->set_network_delegate(m_networkDelegate.get()); - m_urlRequestContext->set_enable_brotli(true); - m_urlRequestContext->set_host_resolver(m_hostResolver.get()); - // this binds factory to io thread - m_weakPtr = m_weakPtrFactory.GetWeakPtr(); - const std::lock_guard<QRecursiveMutex> lock(m_mutex); - generateAllStorage(); - generateJobFactory(); - setGlobalCertificateVerification(); - m_initialized = true; -} - void ProfileIODataQt::initializeOnUIThread() { m_profileAdapter = m_profile->profileAdapter(); DCHECK_CURRENTLY_ON(content::BrowserThread::UI); m_resourceContext.reset(new ResourceContextQt(this)); - ProtocolHandlerRegistry* protocolHandlerRegistry = - ProtocolHandlerRegistryFactory::GetForBrowserContext(m_profile); - DCHECK(protocolHandlerRegistry); - m_protocolHandlerRegistryIOThreadDelegate = protocolHandlerRegistry->io_thread_delegate(); m_cookieDelegate = new CookieMonsterDelegateQt(); m_cookieDelegate->setClient(m_profile->profileAdapter()->cookieStore()); - if (base::FeatureList::IsEnabled(network::features::kNetworkService)) - m_proxyConfigMonitor.reset(new ProxyConfigMonitor(m_profile->GetPrefs())); - else - createProxyConfig(); -} - -void ProfileIODataQt::cancelAllUrlRequests() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_ASSERT(m_urlRequestContext); - - const std::set<const net::URLRequest*> *url_requests = m_urlRequestContext->url_requests(); - std::set<const net::URLRequest*>::const_iterator it = url_requests->begin(); - std::set<const net::URLRequest*>::const_iterator end = url_requests->end(); - for ( ; it != end; ++it) { - net::URLRequest* request = const_cast<net::URLRequest*>(*it); - if (request) - request->Cancel(); - } + m_proxyConfigMonitor.reset(new ProxyConfigMonitor(m_profile->GetPrefs())); } -void ProfileIODataQt::generateAllStorage() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - const std::lock_guard<QRecursiveMutex> lock(m_mutex); - generateStorage(); - generateCookieStore(); - generateUserAgent(); - generateHttpCache(); - m_updateAllStorage = false; -} - -void ProfileIODataQt::generateStorage() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_ASSERT(m_urlRequestContext); -// Q_ASSERT(!m_mutex.tryLock()); // assert locked - - // We must stop all requests before deleting their backends. - if (m_storage) { - m_urlRequestContext->proxy_resolution_service()->OnShutdown(); - m_restrictedCookieManagerBindings.CloseAllBindings(); - m_cookieDelegate->setCookieMonster(nullptr); - m_storage->set_cookie_store(nullptr); - cancelAllUrlRequests(); - // we need to get rid of dangling pointer due to coming storage deletion - m_urlRequestContext->set_http_transaction_factory(nullptr); - m_httpNetworkSession.reset(); - m_transportSecurityPersister.reset(); - } - - m_storage.reset(new net::URLRequestContextStorage(m_urlRequestContext.get())); - - net::ProxyConfigService *proxyConfigService = m_proxyConfigService.fetchAndStoreAcquire(0); - Q_ASSERT(proxyConfigService); - - std::unique_ptr<net::CertVerifier> cert_verifier = net::CertVerifier::CreateDefault(s_certNetFetcher); - net::CertVerifier::Config config; - // Enable revocation checking: - config.enable_rev_checking = true; - // Mirroring Android WebView (we have no beef with Symantec, and our users might use them): - config.disable_symantec_enforcement = true; - cert_verifier->SetConfig(config); - - m_storage->set_cert_verifier(std::move(cert_verifier)); - std::unique_ptr<net::MultiLogCTVerifier> ct_verifier(new net::MultiLogCTVerifier()); - std::vector<scoped_refptr<const net::CTLogVerifier>> ct_logs; - for (const auto &ct_log : certificate_transparency::GetKnownLogs()) { - scoped_refptr<const net::CTLogVerifier> log_verifier = - net::CTLogVerifier::Create(std::string(ct_log.log_key, ct_log.log_key_length), - ct_log.log_name); - if (!log_verifier) - continue; - ct_logs.push_back(std::move(log_verifier)); - } - ct_verifier->AddLogs(ct_logs); - m_storage->set_cert_transparency_verifier(std::move(ct_verifier)); - m_storage->set_ct_policy_enforcer(base::WrapUnique(new net::DefaultCTPolicyEnforcer())); - m_storage->set_ssl_config_service(std::make_unique<net::SSLConfigServiceDefaults>()); - if (!m_httpAuthPreferences) { - m_httpAuthPreferences.reset(new net::HttpAuthPreferences()); - std::string serverWhitelist = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kAuthServerWhitelist); - m_httpAuthPreferences->SetServerWhitelist(serverWhitelist); - } - m_storage->set_http_auth_handler_factory(net::HttpAuthHandlerFactory::CreateDefault( - m_httpAuthPreferences.get())); - m_storage->set_transport_security_state(std::make_unique<net::TransportSecurityState>()); - - if (!m_dataPath.isEmpty()) { - scoped_refptr<base::SequencedTaskRunner> background_task_runner( - base::CreateSequencedTaskRunnerWithTraits( - {base::MayBlock(), - base::TaskPriority::BEST_EFFORT, - base::TaskShutdownBehavior::BLOCK_SHUTDOWN})); - m_transportSecurityPersister = - std::make_unique<net::TransportSecurityPersister>( - m_urlRequestContext->transport_security_state(), - toFilePath(m_dataPath), - background_task_runner); - }; - - m_storage->set_http_server_properties(std::unique_ptr<net::HttpServerProperties>( - new net::HttpServerPropertiesImpl)); - - // The System Proxy Resolver has issues on Windows with unconfigured network cards, - // which is why we want to use the v8 one - if (!m_dhcpPacFileFetcherFactory) - m_dhcpPacFileFetcherFactory.reset(new net::DhcpPacFileFetcherFactory); - - proxy_resolver::mojom::ProxyResolverFactoryPtr proxyResolver(std::move(m_proxyResolverFactoryInterface)); - m_storage->set_proxy_resolution_service(network::CreateProxyResolutionServiceUsingMojoFactory( - std::move(proxyResolver), - std::unique_ptr<net::ProxyConfigService>(proxyConfigService), - net::PacFileFetcherImpl::CreateWithFileUrlSupport(m_urlRequestContext.get()), - m_dhcpPacFileFetcherFactory->Create(m_urlRequestContext.get()), - m_urlRequestContext->host_resolver(), - nullptr /* NetLog */, - m_urlRequestContext->network_delegate())); - - m_storage->set_ftp_auth_cache(std::make_unique<net::FtpAuthCache>()); -} - - -void ProfileIODataQt::generateCookieStore() +void ProfileIODataQt::clearHttpCache() { - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_ASSERT(m_urlRequestContext); - - const std::lock_guard<QRecursiveMutex> lock(m_mutex); - - // FIXME: Add code to remove the old channel-id database. - // TODO(nharper): Remove the following when no longer needed - see - // crbug.com/903642. -// base::PostTaskWithTraits( -// FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, -// base::BindOnce(DeleteChannelIDFiles, path.Append(chrome::kChannelIDFilename))); - - std::unique_ptr<net::CookieStore> cookieStore; - switch (m_persistentCookiesPolicy) { - case ProfileAdapter::NoPersistentCookies: - cookieStore = content::CreateCookieStore( - content::CookieStoreConfig( - base::FilePath(), - false, - false, - nullptr), - nullptr); - break; - case ProfileAdapter::AllowPersistentCookies: - cookieStore = content::CreateCookieStore( - content::CookieStoreConfig( - toFilePath(m_cookiesPath), - false, - true, - nullptr), - nullptr); - break; - case ProfileAdapter::ForcePersistentCookies: - cookieStore = content::CreateCookieStore( - content::CookieStoreConfig( - toFilePath(m_cookiesPath), - true, - true, - nullptr), - nullptr); - break; - } - - net::CookieMonster * const cookieMonster = static_cast<net::CookieMonster*>(cookieStore.get()); - m_cookieDelegate->setCookieMonster(cookieMonster); - m_storage->set_cookie_store(std::move(cookieStore)); - - const std::vector<std::string> cookieableSchemes(kCookieableSchemes, - kCookieableSchemes + base::size(kCookieableSchemes)); - cookieMonster->SetCookieableSchemes(cookieableSchemes, base::DoNothing()); -} - -void ProfileIODataQt::generateUserAgent() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_ASSERT(m_urlRequestContext); - Q_ASSERT(m_storage); - - const std::lock_guard<QRecursiveMutex> lock(m_mutex); - m_storage->set_http_user_agent_settings(std::unique_ptr<net::HttpUserAgentSettings>( - new net::StaticHttpUserAgentSettings(m_httpAcceptLanguage.toStdString(), - m_httpUserAgent.toStdString()))); -} - -void ProfileIODataQt::generateHttpCache() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_ASSERT(m_urlRequestContext); - Q_ASSERT(m_storage); - - const std::lock_guard<QRecursiveMutex> lock(m_mutex); - - net::HttpCache::DefaultBackend* main_backend = 0; - switch (m_httpCacheType) { - case ProfileAdapter::MemoryHttpCache: - main_backend = - new net::HttpCache::DefaultBackend( - net::MEMORY_CACHE, - net::CACHE_BACKEND_DEFAULT, - base::FilePath(), - m_httpCacheMaxSize - ); - break; - case ProfileAdapter::DiskHttpCache: - main_backend = - new net::HttpCache::DefaultBackend( - net::DISK_CACHE, - net::CACHE_BACKEND_DEFAULT, - toFilePath(m_httpCachePath), - m_httpCacheMaxSize - ); - break; - case ProfileAdapter::NoCache: - // It's safe to not create BackendFactory. - break; - } - - net::HttpCache *cache = 0; - net::HttpNetworkSession::Context network_session_context = - generateNetworkSessionContext(m_urlRequestContext.get()); - net::HttpNetworkSession::Params network_session_params = - generateNetworkSessionParams(m_ignoreCertificateErrors); - - if (!m_httpNetworkSession - || !doNetworkSessionParamsMatch(network_session_params, m_httpNetworkSession->params()) - || !doNetworkSessionContextMatch(network_session_context, m_httpNetworkSession->context())) { - m_httpNetworkSession.reset(new net::HttpNetworkSession(network_session_params, - network_session_context)); - } - - cache = new net::HttpCache(m_httpNetworkSession.get(), - std::unique_ptr<net::HttpCache::DefaultBackend>(main_backend), false); - - m_storage->set_http_transaction_factory(std::unique_ptr<net::HttpCache>(cache)); -} - -void ProfileIODataQt::generateJobFactory() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_ASSERT(m_urlRequestContext); - Q_ASSERT(!m_jobFactory); - - const std::lock_guard<QRecursiveMutex> lock(m_mutex); - m_updateJobFactory = false; - - std::unique_ptr<net::URLRequestJobFactoryImpl> jobFactory(new net::URLRequestJobFactoryImpl()); - for (auto &it : m_protocolHandlers) - jobFactory->SetProtocolHandler(it.first, base::WrapUnique(it.second.release())); - m_protocolHandlers.clear(); - - jobFactory->SetProtocolHandler(url::kDataScheme, - std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>( - new net::DataProtocolHandler())); - scoped_refptr<base::TaskRunner> taskRunner(base::CreateTaskRunnerWithTraits({base::MayBlock(), - base::TaskPriority::BEST_EFFORT, - base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})); - jobFactory->SetProtocolHandler(url::kFileScheme, - std::make_unique<net::FileProtocolHandler>(taskRunner)); - jobFactory->SetProtocolHandler(url::kFtpScheme, - net::FtpProtocolHandler::Create(m_urlRequestContext->host_resolver(), m_urlRequestContext->ftp_auth_cache())); - - m_installedCustomSchemes = m_customUrlSchemes; - for (const QByteArray &scheme : qAsConst(m_installedCustomSchemes)) { - jobFactory->SetProtocolHandler(scheme.toStdString(), - std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>( - new CustomProtocolHandler(m_profileAdapter))); - } - - m_baseJobFactory = jobFactory.get(); - - // Set up interceptors in the reverse order. - std::unique_ptr<net::URLRequestJobFactory> topJobFactory = std::move(jobFactory); - content::URLRequestInterceptorScopedVector::reverse_iterator i; - for (i = m_requestInterceptors.rbegin(); i != m_requestInterceptors.rend(); ++i) { - topJobFactory.reset(new net::URLRequestInterceptingJobFactory(std::move(topJobFactory), - std::move(*i))); + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + if (!m_clearHttpCacheInProgress) { + m_clearHttpCacheInProgress = true; + content::BrowsingDataRemover *remover = + content::BrowserContext::GetBrowsingDataRemover(m_profileAdapter->profile()); + remover->AddObserver(&m_removerObserver); + remover->RemoveAndReply(base::Time(), base::Time::Max(), + content::BrowsingDataRemover::DATA_TYPE_CACHE, + content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB | + content::BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB, + &m_removerObserver); } - - m_requestInterceptors.clear(); - - m_jobFactory = std::move(topJobFactory); - - m_urlRequestContext->set_job_factory(m_jobFactory.get()); } -void ProfileIODataQt::regenerateJobFactory() +void ProfileIODataQt::removeBrowsingDataRemoverObserver() { - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_ASSERT(m_urlRequestContext); - Q_ASSERT(m_jobFactory); - Q_ASSERT(m_baseJobFactory); - - const std::lock_guard<QRecursiveMutex> lock(m_mutex); - m_updateJobFactory = false; - - if (m_customUrlSchemes == m_installedCustomSchemes) - return; - - for (const QByteArray &scheme : qAsConst(m_installedCustomSchemes)) { - m_baseJobFactory->SetProtocolHandler(scheme.toStdString(), nullptr); - } - - m_installedCustomSchemes = m_customUrlSchemes; - for (const QByteArray &scheme : qAsConst(m_installedCustomSchemes)) { - m_baseJobFactory->SetProtocolHandler(scheme.toStdString(), - std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>( - new CustomProtocolHandler(m_profileAdapter))); - } + content::BrowsingDataRemover *remover = + content::BrowserContext::GetBrowsingDataRemover(m_profileAdapter->profile()); + remover->RemoveObserver(&m_removerObserver); } -void ProfileIODataQt::setGlobalCertificateVerification() +BrowsingDataRemoverObserverQt::BrowsingDataRemoverObserverQt(ProfileIODataQt *profileIOData) + : m_profileIOData(profileIOData) { - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - const std::lock_guard<QRecursiveMutex> lock(m_mutex); - if (m_useForGlobalCertificateVerification) { -#if defined(USE_NSS_CERTS) - // Set request context used by NSS for OCSP requests. - net::SetURLRequestContextForNSSHttpIO(m_urlRequestContext.get()); -#endif - if (!s_certNetFetcher) - s_certNetFetcher = base::MakeRefCounted<net::CertNetFetcherImpl>(); - s_certNetFetcher->SetURLRequestContext(m_urlRequestContext.get()); - } } -void ProfileIODataQt::setRequestContextData(content::ProtocolHandlerMap *protocolHandlers, - content::URLRequestInterceptorScopedVector request_interceptors) +void BrowsingDataRemoverObserverQt::OnBrowsingDataRemoverDone(uint64_t) { - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - Q_ASSERT(!m_initialized); - m_requestInterceptors = std::move(request_interceptors); - std::swap(m_protocolHandlers, *protocolHandlers); + Q_ASSERT(m_profileIOData->m_clearHttpCacheInProgress); + m_profileIOData->removeBrowsingDataRemoverObserver(); + m_profileIOData->m_clearHttpCacheInProgress = false; + m_profileIOData->resetNetworkContext(); } void ProfileIODataQt::setFullConfiguration() { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); m_persistentCookiesPolicy = m_profileAdapter->persistentCookiesPolicy(); - m_cookiesPath = m_profileAdapter->cookiesPath(); m_httpAcceptLanguage = m_profileAdapter->httpAcceptLanguage(); m_httpUserAgent = m_profileAdapter->httpUserAgent(); m_httpCacheType = m_profileAdapter->httpCacheType(); m_httpCachePath = m_profileAdapter->httpCachePath(); m_httpCacheMaxSize = m_profileAdapter->httpCacheMaxSize(); - m_customUrlSchemes = m_profileAdapter->customUrlSchemes(); - m_useForGlobalCertificateVerification = m_profileAdapter->isUsedForGlobalCertificateVerification(); m_dataPath = m_profileAdapter->dataPath(); + m_storageName = m_profileAdapter->storageName(); + m_inMemoryOnly = m_profileAdapter->isOffTheRecord() || m_storageName.isEmpty(); } -void ProfileIODataQt::requestStorageGeneration() { - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - const std::lock_guard<QRecursiveMutex> lock(m_mutex); - if (m_initialized && !m_updateAllStorage) { - m_updateAllStorage = true; - if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) - createProxyConfig(); - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&ProfileIODataQt::generateAllStorage, m_weakPtr)); - } -} - -// TODO(miklocek): mojofy ProxyConfigServiceQt -void ProfileIODataQt::createProxyConfig() -{ - Q_ASSERT(!base::FeatureList::IsEnabled(network::features::kNetworkService)); - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - const std::lock_guard<QRecursiveMutex> lock(m_mutex); - // 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(). - Q_ASSERT(m_proxyConfigService == 0); - m_proxyConfigService = - new ProxyConfigServiceQt( - m_profileAdapter->profile()->GetPrefs(), - base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO})); - //pass interface to io thread - m_proxyResolverFactoryInterface = ChromeMojoProxyResolverFactory::CreateWithSelfOwnedReceiver(); -} - -void ProfileIODataQt::updateStorageSettings() +void ProfileIODataQt::resetNetworkContext() { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - - const std::lock_guard<QRecursiveMutex> lock(m_mutex); setFullConfiguration(); - - base::Token groupId = content::BrowserContext::GetServiceInstanceGroupFor(m_profile); - if (file::GetUserDirForInstanceGroup(groupId) != toFilePath(m_profileAdapter->dataPath())) { - file::ForgetServiceInstanceGroupUserDirAssociation(groupId); - file::AssociateServiceInstanceGroupWithUserDir(groupId, toFilePath(m_profileAdapter->dataPath())); - } - if (!m_pendingStorageRequestGeneration) - requestStorageGeneration(); -} - -void ProfileIODataQt::updateCookieStore() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - const std::lock_guard<QRecursiveMutex> lock(m_mutex); - m_persistentCookiesPolicy = m_profileAdapter->persistentCookiesPolicy(); - m_cookiesPath = m_profileAdapter->cookiesPath(); - if (!m_pendingStorageRequestGeneration) - requestStorageGeneration(); -} - -void ProfileIODataQt::updateUserAgent() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - const std::lock_guard<QRecursiveMutex> lock(m_mutex); - m_httpAcceptLanguage = m_profileAdapter->httpAcceptLanguage(); - m_httpUserAgent = m_profileAdapter->httpUserAgent(); - if (!m_pendingStorageRequestGeneration) - requestStorageGeneration(); -} - -void ProfileIODataQt::updateHttpCache() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - const std::lock_guard<QRecursiveMutex> lock(m_mutex); - m_httpCacheType = m_profileAdapter->httpCacheType(); - m_httpCachePath = m_profileAdapter->httpCachePath(); - m_httpCacheMaxSize = m_profileAdapter->httpCacheMaxSize(); - - if (m_httpCacheType == ProfileAdapter::NoCache) { - m_pendingStorageRequestGeneration = true; - content::BrowsingDataRemover *remover = - content::BrowserContext::GetBrowsingDataRemover(m_profileAdapter->profile()); - remover->AddObserver(&m_removerObserver); - remover->RemoveAndReply(base::Time(), base::Time::Max(), - content::BrowsingDataRemover::DATA_TYPE_CACHE, - content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB | - content::BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB, - &m_removerObserver); - return; - } - if (!m_pendingStorageRequestGeneration) - requestStorageGeneration(); -} - -void ProfileIODataQt::updateJobFactory() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - const std::lock_guard<QRecursiveMutex> lock(m_mutex); - - m_customUrlSchemes = m_profileAdapter->customUrlSchemes(); - - if (m_initialized && !m_updateJobFactory) { - m_updateJobFactory = true; - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&ProfileIODataQt::regenerateJobFactory, m_weakPtr)); - } -} - -void ProfileIODataQt::updateRequestInterceptor() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - const std::lock_guard<QRecursiveMutex> lock(m_mutex); - m_requestInterceptor = m_profileAdapter->requestInterceptor(); - m_hasPageInterceptors = m_profileAdapter->hasPageRequestInterceptor(); - if (m_requestInterceptor) - m_isInterceptorDeprecated = m_requestInterceptor->property("deprecated").toBool(); - else - m_isInterceptorDeprecated = false; - // We in this case do not need to regenerate any Chromium classes. -} - -bool ProfileIODataQt::isInterceptorDeprecated() const -{ - return m_isInterceptorDeprecated; -} - -QWebEngineUrlRequestInterceptor *ProfileIODataQt::acquireInterceptor() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - m_mutex.lock(); - return m_requestInterceptor; -} - -QWebEngineUrlRequestInterceptor *ProfileIODataQt::requestInterceptor() -{ - return m_requestInterceptor; -} - -bool ProfileIODataQt::hasPageInterceptors() -{ - // used in NetworkDelegateQt::OnBeforeURLRequest - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - return m_hasPageInterceptors; -} - -void ProfileIODataQt::releaseInterceptor() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - m_mutex.unlock(); -} - -bool ProfileIODataQt::canSetCookie(const QUrl &firstPartyUrl, const QByteArray &cookieLine, const QUrl &url) const -{ - return m_cookieDelegate->canSetCookie(firstPartyUrl,cookieLine, url); + content::BrowserContext::ForEachStoragePartition( + m_profile, base::BindRepeating([](content::StoragePartition *storage) { + auto storage_impl = static_cast<content::StoragePartitionImpl *>(storage); + storage_impl->ResetURLLoaderFactories(); + storage_impl->ResetNetworkContext(); + })); } bool ProfileIODataQt::canGetCookies(const QUrl &firstPartyUrl, const QUrl &url) const @@ -806,19 +199,6 @@ bool ProfileIODataQt::canGetCookies(const QUrl &firstPartyUrl, const QUrl &url) return m_cookieDelegate->canGetCookies(firstPartyUrl, url); } -void ProfileIODataQt::updateUsedForGlobalCertificateVerification() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - const std::lock_guard<QRecursiveMutex> lock(m_mutex); - if (m_useForGlobalCertificateVerification == m_profileAdapter->isUsedForGlobalCertificateVerification()) - return; - m_useForGlobalCertificateVerification = m_profileAdapter->isUsedForGlobalCertificateVerification(); - - if (m_useForGlobalCertificateVerification) - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&ProfileIODataQt::setGlobalCertificateVerification, m_weakPtr)); -} - #if QT_CONFIG(ssl) ClientCertificateStoreData *ProfileIODataQt::clientCertificateStoreData() { @@ -831,53 +211,44 @@ std::unique_ptr<net::ClientCertStore> ProfileIODataQt::CreateClientCertStore() #if QT_CONFIG(ssl) return std::unique_ptr<net::ClientCertStore>(new ClientCertOverrideStore(m_clientCertificateStoreData)); #else - return nullptr; + return std::unique_ptr<net::ClientCertStore>(new ClientCertOverrideStore(nullptr)); #endif } -void ProfileIODataQt::CreateRestrictedCookieManager(network::mojom::RestrictedCookieManagerRequest request, - network::mojom::RestrictedCookieManagerRole role, - const url::Origin &origin, - bool is_service_worker, - int32_t process_id, - int32_t routing_id) +void ProfileIODataQt::ConfigureNetworkContextParams(bool in_memory, + const base::FilePath &relative_partition_path, + network::mojom::NetworkContextParams *network_context_params, + network::mojom::CertVerifierCreationParams *cert_verifier_creation_params) { - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - m_restrictedCookieManagerBindings.AddBinding( - std::make_unique<RestrictedCookieManagerQt>( - m_weakPtr, - role, urlRequestContext()->cookie_store(), - &m_cookieSettings, origin, - is_service_worker, process_id, routing_id), - std::move(request)); -} + setFullConfiguration(); -network::mojom::NetworkContextParamsPtr ProfileIODataQt::CreateNetworkContextParams() -{ - network::mojom::NetworkContextParamsPtr network_context_params = - SystemNetworkContextManager::GetInstance()->CreateDefaultNetworkContextParams(); + SystemNetworkContextManager::GetInstance()->ConfigureDefaultNetworkContextParams(network_context_params); + + // FIXME: Faking old behavior to allow not enabling OCSP + network_context_params->initial_ssl_config->rev_checking_enabled = !ProfileAdapter::s_profileForGlobalCertificateVerification.isNull(); - network_context_params->context_name = m_profile->profileAdapter()->storageName().toStdString(); + network_context_params->context_name = m_storageName.toStdString(); + network_context_params->user_agent = m_httpUserAgent.toStdString(); network_context_params->accept_language = m_httpAcceptLanguage.toStdString(); network_context_params->enable_referrers = true; - network_context_params->enable_encrypted_cookies = false; // ??? -// network_context_params->proxy_resolver_factory = std::move(m_proxyResolverFactoryInterface); + // Encrypted cookies requires os_crypt, which currently has issues for us on Linux. + network_context_params->enable_encrypted_cookies = false; network_context_params->http_cache_enabled = m_httpCacheType != ProfileAdapter::NoCache; network_context_params->http_cache_max_size = m_httpCacheMaxSize; - if (m_httpCacheType == ProfileAdapter::DiskHttpCache) + if (m_httpCacheType == ProfileAdapter::DiskHttpCache && !m_httpCachePath.isEmpty() && !m_inMemoryOnly && !in_memory) network_context_params->http_cache_path = toFilePath(m_httpCachePath); - if (m_persistentCookiesPolicy != ProfileAdapter::NoPersistentCookies) { + if (m_persistentCookiesPolicy != ProfileAdapter::NoPersistentCookies && !m_inMemoryOnly && !in_memory) { base::FilePath cookie_path = toFilePath(m_dataPath); cookie_path = cookie_path.AppendASCII("Cookies"); network_context_params->cookie_path = cookie_path; - network_context_params->restore_old_session_cookies = false; - network_context_params->persist_session_cookies = m_persistentCookiesPolicy == ProfileAdapter::ForcePersistentCookies; + network_context_params->restore_old_session_cookies = m_persistentCookiesPolicy == ProfileAdapter::ForcePersistentCookies; + network_context_params->persist_session_cookies = m_persistentCookiesPolicy != ProfileAdapter::NoPersistentCookies; } - if (!m_dataPath.isEmpty()) { + if (!m_inMemoryOnly && !in_memory) { network_context_params->http_server_properties_path = toFilePath(m_dataPath).AppendASCII("Network Persistent State"); network_context_params->transport_security_persister_path = toFilePath(m_dataPath); } @@ -886,22 +257,13 @@ network::mojom::NetworkContextParamsPtr ProfileIODataQt::CreateNetworkContextPar network_context_params->enable_ftp_url_support = true; #endif // !BUILDFLAG(DISABLE_FTP_SUPPORT) -// proxy_config_monitor_.AddToNetworkContextParams(network_context_params.get()); - -// network_context_params->enable_certificate_reporting = true; -// network_context_params->enable_expect_ct_reporting = true; network_context_params->enforce_chrome_ct_policy = false; - network_context_params->primary_network_context = m_useForGlobalCertificateVerification; - if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { - // Should be initialized with existing per-profile CORS access lists. - network_context_params->cors_origin_access_list = - m_profile->GetSharedCorsOriginAccessList()->GetOriginAccessList().CreateCorsOriginAccessPatternsList(); - } - - m_proxyConfigMonitor->AddToNetworkContextParams(&*network_context_params); + // Should be initialized with existing per-profile CORS access lists. + network_context_params->cors_origin_access_list = + m_profile->GetSharedCorsOriginAccessList()->GetOriginAccessList().CreateCorsOriginAccessPatternsList(); - return network_context_params; + m_proxyConfigMonitor->AddToNetworkContextParams(network_context_params); } // static @@ -918,24 +280,4 @@ ProfileIODataQt *ProfileIODataQt::FromResourceContext(content::ResourceContext * return static_cast<ResourceContextQt *>(resource_context)->m_io_data; } -void ProfileIODataQt::removeBrowsingDataRemoverObserver() -{ - content::BrowsingDataRemover *remover = - content::BrowserContext::GetBrowsingDataRemover(m_profileAdapter->profile()); - remover->RemoveObserver(&m_removerObserver); -} - -BrowsingDataRemoverObserverQt::BrowsingDataRemoverObserverQt(ProfileIODataQt *profileIOData) - : m_profileIOData(profileIOData) -{ -} - -void BrowsingDataRemoverObserverQt::OnBrowsingDataRemoverDone() -{ - Q_ASSERT(m_profileIOData->m_pendingStorageRequestGeneration); - m_profileIOData->requestStorageGeneration(); - m_profileIOData->removeBrowsingDataRemoverObserver(); - m_profileIOData->m_pendingStorageRequestGeneration = false; -} - } // namespace QtWebEngineCore diff --git a/src/core/profile_io_data_qt.h b/src/core/profile_io_data_qt.h index 882602012..e44d838dd 100644 --- a/src/core/profile_io_data_qt.h +++ b/src/core/profile_io_data_qt.h @@ -40,18 +40,12 @@ #ifndef PROFILE_IO_DATA_QT_H #define PROFILE_IO_DATA_QT_H -#include "profile_adapter.h" #include "content/public/browser/browsing_data_remover.h" -#include "content/public/common/url_loader_throttle.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/custom_handlers/protocol_handler_registry.h" #include "extensions/buildflags/buildflags.h" -#include "mojo/public/cpp/bindings/strong_binding_set.h" + #include "net/proxy_config_monitor.h" -#include "services/network/cookie_settings.h" -#include "services/network/public/mojom/network_context.mojom.h" -#include "services/network/public/mojom/restricted_cookie_manager.mojom.h" -#include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h" +#include "profile_adapter.h" #include <QtCore/QString> #include <QtCore/QPointer> @@ -59,16 +53,6 @@ namespace net { class ClientCertStore; -class DhcpPacFileFetcherFactory; -class HttpAuthPreferences; -class HttpNetworkSession; -class HostResolver; -class NetworkDelegate; -class ProxyConfigService; -class URLRequestContext; -class URLRequestContextStorage; -class URLRequestJobFactoryImpl; -class TransportSecurityPersister; } namespace extensions { @@ -81,18 +65,16 @@ struct ClientCertificateStoreData; class ProfileIODataQt; class ProfileQt; - class BrowsingDataRemoverObserverQt : public content::BrowsingDataRemover::Observer { public: BrowsingDataRemoverObserverQt(ProfileIODataQt *profileIOData); - void OnBrowsingDataRemoverDone() override; + void OnBrowsingDataRemoverDone(uint64_t) override; private: ProfileIODataQt *m_profileIOData; }; - // ProfileIOData contains data that lives on the IOthread // we still use shared memebers and use mutex which breaks // idea for this object, but this is wip. @@ -105,60 +87,24 @@ public: QPointer<ProfileAdapter> profileAdapter(); content::ResourceContext *resourceContext(); - net::URLRequestContext *urlRequestContext(); #if BUILDFLAG(ENABLE_EXTENSIONS) extensions::ExtensionSystemQt* GetExtensionSystem(); #endif // BUILDFLAG(ENABLE_EXTENSIONS) - ProtocolHandlerRegistry::IOThreadDelegate *protocolHandlerRegistryIOThreadDelegate() - { - return m_protocolHandlerRegistryIOThreadDelegate.get(); - } - - void initializeOnIOThread(); void initializeOnUIThread(); // runs on ui thread void shutdownOnUIThread(); // runs on ui thread - void cancelAllUrlRequests(); - void generateAllStorage(); - void generateStorage(); - void generateCookieStore(); - void generateHttpCache(); - void generateUserAgent(); - void generateJobFactory(); - void regenerateJobFactory(); - bool canSetCookie(const QUrl &firstPartyUrl, const QByteArray &cookieLine, const QUrl &url) const; bool canGetCookies(const QUrl &firstPartyUrl, const QUrl &url) const; - void setGlobalCertificateVerification(); - - // Used in NetworkDelegateQt::OnBeforeURLRequest. - bool isInterceptorDeprecated() const; // Remove for Qt6 - QWebEngineUrlRequestInterceptor *acquireInterceptor(); // Remove for Qt6 - void releaseInterceptor(); - QWebEngineUrlRequestInterceptor *requestInterceptor(); - void setRequestContextData(content::ProtocolHandlerMap *protocolHandlers, - content::URLRequestInterceptorScopedVector request_interceptors); void setFullConfiguration(); // runs on ui thread - void updateStorageSettings(); // runs on ui thread - void updateUserAgent(); // runs on ui thread - void updateCookieStore(); // runs on ui thread - void updateHttpCache(); // runs on ui thread - void updateJobFactory(); // runs on ui thread - void updateRequestInterceptor(); // runs on ui thread - void requestStorageGeneration(); //runs on ui thread - void createProxyConfig(); //runs on ui thread - void updateUsedForGlobalCertificateVerification(); // runs on ui thread - bool hasPageInterceptors(); - - void CreateRestrictedCookieManager(network::mojom::RestrictedCookieManagerRequest request, - network::mojom::RestrictedCookieManagerRole role, - const url::Origin &origin, - bool is_service_worker, - int32_t process_id, - int32_t routing_id); - - network::mojom::NetworkContextParamsPtr CreateNetworkContextParams(); + void resetNetworkContext(); // runs on ui thread + void clearHttpCache(); // runs on ui thread + bool isClearHttpCacheInProgress() { return m_clearHttpCacheInProgress; } + + void ConfigureNetworkContextParams(bool in_memory, + const base::FilePath &relative_partition_path, + network::mojom::NetworkContextParams *network_context_params, + network::mojom::CertVerifierCreationParams *cert_verifier_creation_params); #if QT_CONFIG(ssl) ClientCertificateStoreData *clientCertificateStoreData(); @@ -168,7 +114,6 @@ public: static ProfileIODataQt *FromResourceContext(content::ResourceContext *resource_context); base::WeakPtr<ProfileIODataQt> getWeakPtrOnIOThread(); - base::WeakPtr<ProfileIODataQt> getWeakPtrOnUIThread(); CookieMonsterDelegateQt *cookieDelegate() const { return m_cookieDelegate.get(); } @@ -176,42 +121,21 @@ private: void removeBrowsingDataRemoverObserver(); ProfileQt *m_profile; - std::unique_ptr<net::URLRequestContextStorage> m_storage; - std::unique_ptr<net::NetworkDelegate> m_networkDelegate; std::unique_ptr<content::ResourceContext> m_resourceContext; - std::unique_ptr<net::URLRequestContext> m_urlRequestContext; - std::unique_ptr<net::HttpNetworkSession> m_httpNetworkSession; - scoped_refptr<ProtocolHandlerRegistry::IOThreadDelegate> - m_protocolHandlerRegistryIOThreadDelegate; - std::unique_ptr<net::DhcpPacFileFetcherFactory> m_dhcpPacFileFetcherFactory; - std::unique_ptr<net::HttpAuthPreferences> m_httpAuthPreferences; - std::unique_ptr<net::URLRequestJobFactory> m_jobFactory; - std::unique_ptr<net::TransportSecurityPersister> m_transportSecurityPersister; - std::unique_ptr<net::HostResolver> m_hostResolver; - base::WeakPtr<ProfileIODataQt> m_weakPtr; scoped_refptr<CookieMonsterDelegateQt> m_cookieDelegate; - content::URLRequestInterceptorScopedVector m_requestInterceptors; - content::ProtocolHandlerMap m_protocolHandlers; - mojo::InterfacePtrInfo<proxy_resolver::mojom::ProxyResolverFactory> m_proxyResolverFactoryInterface; - net::URLRequestJobFactoryImpl *m_baseJobFactory = nullptr; - QAtomicPointer<net::ProxyConfigService> m_proxyConfigService; QPointer<ProfileAdapter> m_profileAdapter; // never dereferenced in IO thread and it is passed by qpointer ProfileAdapter::PersistentCookiesPolicy m_persistentCookiesPolicy; - mojo::StrongBindingSet<network::mojom::RestrictedCookieManager> m_restrictedCookieManagerBindings; std::unique_ptr<ProxyConfigMonitor> m_proxyConfigMonitor; #if QT_CONFIG(ssl) ClientCertificateStoreData *m_clientCertificateStoreData; #endif - QString m_cookiesPath; QString m_httpAcceptLanguage; QString m_httpUserAgent; ProfileAdapter::HttpCacheType m_httpCacheType; QString m_httpCachePath; - QList<QByteArray> m_customUrlSchemes; - QList<QByteArray> m_installedCustomSchemes; - QWebEngineUrlRequestInterceptor* m_requestInterceptor = nullptr; - network::CookieSettings m_cookieSettings; + QString m_storageName; + bool m_inMemoryOnly; #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) QMutex m_mutex{QMutex::Recursive}; using QRecursiveMutex = QMutex; @@ -219,17 +143,10 @@ private: QRecursiveMutex m_mutex; #endif int m_httpCacheMaxSize = 0; - bool m_initialized = false; - bool m_updateAllStorage = false; - bool m_updateJobFactory = false; - bool m_ignoreCertificateErrors = false; - bool m_useForGlobalCertificateVerification = false; - bool m_hasPageInterceptors = false; BrowsingDataRemoverObserverQt m_removerObserver; - base::WeakPtrFactory<ProfileIODataQt> m_weakPtrFactory; // this should be always the last member QString m_dataPath; - bool m_pendingStorageRequestGeneration = false; - volatile bool m_isInterceptorDeprecated = false; // Remove for Qt6 + bool m_clearHttpCacheInProgress = false; + base::WeakPtrFactory<ProfileIODataQt> m_weakPtrFactory; // this should be always the last member DISALLOW_COPY_AND_ASSIGN(ProfileIODataQt); friend class BrowsingDataRemoverObserverQt; diff --git a/src/core/profile_qt.cpp b/src/core/profile_qt.cpp index be55e7c49..36303605f 100644 --- a/src/core/profile_qt.cpp +++ b/src/core/profile_qt.cpp @@ -41,10 +41,8 @@ #include "profile_adapter.h" #include "browsing_data_remover_delegate_qt.h" -#include "command_line_pref_store_qt.h" #include "download_manager_delegate_qt.h" #include "net/ssl_host_state_delegate_qt.h" -#include "net/url_request_context_getter_qt.h" #include "permission_manager_qt.h" #include "platform_notification_service_qt.h" #include "qtwebenginecoreglobal_p.h" @@ -52,8 +50,10 @@ #include "web_engine_library_info.h" #include "web_engine_context.h" +#include "base/barrier_closure.h" #include "base/time/time.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/cors_origin_pattern_setter.h" #include "content/public/browser/shared_cors_origin_access_list.h" #include "content/public/browser/storage_partition.h" @@ -76,7 +76,6 @@ #if BUILDFLAG(ENABLE_EXTENSIONS) #include "components/guest_view/browser/guest_view_manager.h" -#include "extensions/browser/extension_protocols.h" #include "extensions/browser/pref_names.h" #include "extensions/browser/process_manager.h" #include "extensions/common/constants.h" @@ -112,7 +111,6 @@ ProfileQt::~ProfileQt() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); m_prefServiceAdapter.commit(); - content::BrowserContext::NotifyWillBeDestroyed(this); BrowserContextDependencyManager::GetInstance()->DestroyBrowserContextServices(this); ShutdownStoragePartitions(); m_profileIOData->shutdownOnUIThread(); @@ -145,16 +143,6 @@ bool ProfileQt::IsOffTheRecord() return m_profileAdapter->isOffTheRecord(); } -net::URLRequestContextGetter *ProfileQt::GetRequestContext() -{ - return m_urlRequestContextGetter.get(); -} - -net::URLRequestContextGetter *ProfileQt::CreateMediaRequestContext() -{ - return m_urlRequestContextGetter.get(); -} - content::ResourceContext *ProfileQt::GetResourceContext() { return m_profileIOData->resourceContext(); @@ -176,7 +164,7 @@ content::BrowserPluginGuestManager *ProfileQt::GetGuestManager() storage::SpecialStoragePolicy *ProfileQt::GetSpecialStoragePolicy() { - QT_NOT_YET_IMPLEMENTED + // matches android_webview and chromecast return nullptr; } @@ -221,26 +209,12 @@ content::PermissionControllerDelegate *ProfileQt::GetPermissionControllerDelegat return m_permissionManager.get(); } -net::URLRequestContextGetter *ProfileQt::CreateRequestContext( - content::ProtocolHandlerMap *protocol_handlers, - content::URLRequestInterceptorScopedVector request_interceptors) +content::ClientHintsControllerDelegate *ProfileQt::GetClientHintsControllerDelegate() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK(!m_urlRequestContextGetter.get()); -#if BUILDFLAG(ENABLE_EXTENSIONS) - extensions::InfoMap *extension_info_map = GetExtensionSystem()->info_map(); - (*protocol_handlers)[extensions::kExtensionScheme] = - extensions::CreateExtensionProtocolHandler(IsOffTheRecord(), extension_info_map); -#endif - - m_profileIOData->setRequestContextData(protocol_handlers, std::move(request_interceptors)); - m_profileIOData->updateStorageSettings(); - m_profileIOData->updateRequestInterceptor(); - m_urlRequestContextGetter = new URLRequestContextGetterQt(m_profileIOData.get()); - return m_urlRequestContextGetter.get(); + return nullptr; } -content::ClientHintsControllerDelegate *ProfileQt::GetClientHintsControllerDelegate() +content::StorageNotificationService *ProfileQt::GetStorageNotificationService() { return nullptr; } @@ -250,10 +224,22 @@ void ProfileQt::SetCorsOriginAccessListForOrigin(const url::Origin &source_origi std::vector<network::mojom::CorsOriginPatternPtr> block_patterns, base::OnceClosure closure) { + auto barrier_closure = base::BarrierClosure(2, std::move(closure)); + + // Keep profile storage partitions' NetworkContexts synchronized. + auto profile_setter = base::MakeRefCounted<content::CorsOriginPatternSetter>( + source_origin, + content::CorsOriginPatternSetter::ClonePatterns(allow_patterns), + content::CorsOriginPatternSetter::ClonePatterns(block_patterns), + barrier_closure); + ForEachStoragePartition(this, + base::BindRepeating(&content::CorsOriginPatternSetter::SetLists, + base::RetainedRef(profile_setter.get()))); + m_sharedCorsOriginAccessList->SetForOrigin(source_origin, std::move(allow_patterns), std::move(block_patterns), - std::move(closure)); + barrier_closure); } content::SharedCorsOriginAccessList *ProfileQt::GetSharedCorsOriginAccessList() diff --git a/src/core/profile_qt.h b/src/core/profile_qt.h index f5dc59717..59f5a8c21 100644 --- a/src/core/profile_qt.h +++ b/src/core/profile_qt.h @@ -44,7 +44,6 @@ #include "content/public/browser/content_browser_client.h" #include "content/public/browser/resource_context.h" #include "extensions/buildflags/buildflags.h" -#include "net/url_request/url_request_context.h" #include "pref_service_adapter.h" #include "profile_io_data_qt.h" #include <QtGlobal> @@ -79,16 +78,12 @@ public: base::FilePath GetPath() override; bool IsOffTheRecord() override; - net::URLRequestContextGetter *CreateMediaRequestContext() override; content::ResourceContext *GetResourceContext() override; content::DownloadManagerDelegate *GetDownloadManagerDelegate() override; content::BrowserPluginGuestManager *GetGuestManager() override; storage::SpecialStoragePolicy *GetSpecialStoragePolicy() override; content::PushMessagingService *GetPushMessagingService() override; content::SSLHostStateDelegate *GetSSLHostStateDelegate() override; - net::URLRequestContextGetter *CreateRequestContext( - content::ProtocolHandlerMap *protocol_handlers, - content::URLRequestInterceptorScopedVector request_interceptors) override; std::unique_ptr<content::ZoomLevelDelegate> CreateZoomLevelDelegate( const base::FilePath &partition_path) override; content::PermissionControllerDelegate * GetPermissionControllerDelegate() override; @@ -96,6 +91,7 @@ public: content::BackgroundSyncController *GetBackgroundSyncController() override; content::BrowsingDataRemoverDelegate *GetBrowsingDataRemoverDelegate() override; content::ClientHintsControllerDelegate *GetClientHintsControllerDelegate() override; + content::StorageNotificationService *GetStorageNotificationService() override; void SetCorsOriginAccessListForOrigin(const url::Origin &source_origin, std::vector<network::mojom::CorsOriginPatternPtr> allow_patterns, std::vector<network::mojom::CorsOriginPatternPtr> block_patterns, @@ -106,9 +102,8 @@ public: // Profile implementation: PrefService *GetPrefs() override; const PrefService *GetPrefs() const override; - net::URLRequestContextGetter *GetRequestContext() override; - void Initialize(); + void Initialize(); ProfileAdapter *profileAdapter() { return m_profileAdapter; } content::PlatformNotificationService *platformNotificationService(); @@ -132,7 +127,6 @@ private: friend class ContentBrowserClientQt; friend class ProfileIODataQt; friend class WebContentsAdapter; - scoped_refptr<net::URLRequestContextGetter> m_urlRequestContextGetter; std::unique_ptr<BrowsingDataRemoverDelegateQt> m_removerDelegate; std::unique_ptr<PermissionManagerQt> m_permissionManager; std::unique_ptr<SSLHostStateDelegateQt> m_sslHostStateDelegate; diff --git a/src/core/qtwebengine.gni b/src/core/qtwebengine.gni index b529290c0..11352a3e8 100644 --- a/src/core/qtwebengine.gni +++ b/src/core/qtwebengine.gni @@ -22,7 +22,7 @@ deps = [ "//components/keyed_service/content", "//components/navigation_interception", "//components/network_hints/browser", - "//components/network_hints/common", + "//components/network_hints/common:mojo_bindings", "//components/network_hints/renderer", "//components/visitedlink/browser", "//components/visitedlink/renderer", @@ -31,16 +31,17 @@ deps = [ "//components/spellcheck:buildflags", "//components/proxy_config", "//components/user_prefs", - "//content/public/app:browser", + "//content/public/app", "//content", "//media:media_buildflags", - "//net:net_with_v8", + "//net", "//services/proxy_resolver:lib", "//skia", "//third_party/blink/public:blink", "//ui/accessibility", "//ui/gl", "//qtwebengine/browser:interfaces", + "//qtwebengine/userscript", "//qtwebengine/browser:service_manifests", "//qtwebengine/common:mojo_bindings", ":qtwebengine_sources", @@ -48,7 +49,7 @@ deps = [ ] if (enable_webrtc) { - deps += [ "//third_party/webrtc_overrides" ] + deps += [ "//third_party/webrtc_overrides:webrtc_component" ] } if (use_ozone) { @@ -66,6 +67,10 @@ if (enable_extensions) { ] } +if (is_win) { + data_deps = [ ":qtwebengine_sandbox_win" ] +} + defines = [ "CHROMIUM_VERSION=\"" + chromium_version[0] + "\"" ] diff --git a/src/core/qtwebengine_resources.gni b/src/core/qtwebengine_resources.gni index 749546741..3bf1a5d57 100644 --- a/src/core/qtwebengine_resources.gni +++ b/src/core/qtwebengine_resources.gni @@ -21,11 +21,15 @@ group("qtwebengine_resources") { repack("qtwebengine_repack_resources") { sources = [ "$root_gen_dir/qtwebengine/qt_webengine_resources.pak", - "$root_gen_dir/chrome/browser_resources.pak", "$root_gen_dir/chrome/common_resources.pak", + "$root_gen_dir/chrome/net_internals_resources.pak", "$root_gen_dir/chrome/quota_internals_resources.pak", "$root_gen_dir/components/components_resources.pak", + "$root_gen_dir/components/dev_ui_components_resources.pak", + "$root_gen_dir/content/browser/resources/media/media_internals_resources.pak", + "$root_gen_dir/content/browser/tracing/tracing_resources.pak", "$root_gen_dir/content/content_resources.pak", + "$root_gen_dir/content/dev_ui_content_resources.pak", "$root_gen_dir/mojo/public/js/mojo_bindings_resources.pak", "$root_gen_dir/net/net_resources.pak", "$root_gen_dir/third_party/blink/public/resources/blink_resources.pak", @@ -34,11 +38,15 @@ repack("qtwebengine_repack_resources") { output = "$root_out_dir/qtwebengine_resources.pak" deps = [ "//qtwebengine/browser:qt_webengine_resources", - "//chrome/browser/resources:quota_internals_resources", - "//chrome/browser:resources_grit", + "//chrome/browser/resources/net_internals:net_internals_resources", + "//chrome/browser/resources/quota_internals:quota_internals_resources", "//chrome/common:resources_grit", "//components/resources:components_resources_grit", - "//content:resources_grit", + "//components/resources:dev_ui_components_resources_grit", + "//content/browser/resources/media:media_internals_resources", + "//content/browser/tracing:resources", + "//content:content_resources_grit", + "//content:dev_ui_content_resources_grit", "//mojo/public/js:resources", "//net:net_resources_grit", "//third_party/blink/public:resources_grit", @@ -58,13 +66,30 @@ repack("qtwebengine_repack_resources") { ] } + if (enable_webrtc) { + sources += [ + "$root_gen_dir/content/browser/webrtc/resources/webrtc_internals_resources.pak", + ] + deps += [ + "//content/browser/webrtc/resources", + ] + } + + if (enable_webrtc && enable_extensions) { + sources += [ + "$root_gen_dir/chrome/webrtc_logs_resources.pak", + ] + deps += [ + "//chrome/browser/resources/media:webrtc_logs_resources", + ] + } } repack("qtwebengine_repack_resources_100") { sources = [ + "$root_gen_dir/chrome/renderer_resources_100_percent.pak", "$root_gen_dir/components/components_resources_100_percent.pak", "$root_gen_dir/content/app/resources/content_resources_100_percent.pak", - "$root_gen_dir/chrome/renderer_resources_100_percent.pak", "$root_gen_dir/third_party/blink/public/resources/blink_scaled_resources_100_percent.pak", "$root_gen_dir/ui/resources/ui_resources_100_percent.pak", ] @@ -88,9 +113,9 @@ repack("qtwebengine_repack_resources_100") { repack("qtwebengine_repack_resources_200") { sources = [ + "$root_gen_dir/chrome/renderer_resources_200_percent.pak", "$root_gen_dir/components/components_resources_200_percent.pak", "$root_gen_dir/content/app/resources/content_resources_200_percent.pak", - "$root_gen_dir/chrome/renderer_resources_200_percent.pak", "$root_gen_dir/third_party/blink/public/resources/blink_scaled_resources_200_percent.pak", "$root_gen_dir/ui/resources/ui_resources_200_percent.pak", ] @@ -115,10 +140,12 @@ repack("qtwebengine_repack_resources_200") { repack("qtwebengine_repack_resources_devtools") { sources = [ "$root_gen_dir/content/browser/devtools/devtools_resources.pak", + "$root_gen_dir/third_party/blink/public/resources/inspector_overlay_resources.pak", ] output = "$root_out_dir/qtwebengine_devtools_resources.pak" deps = [ "//content/browser/devtools:devtools_resources_grit", + "//third_party/blink/public:devtools_inspector_resources", ] } diff --git a/src/core/qtwebengine_sources.gni b/src/core/qtwebengine_sources.gni index b4a6b3b83..97d51d68e 100644 --- a/src/core/qtwebengine_sources.gni +++ b/src/core/qtwebengine_sources.gni @@ -47,9 +47,14 @@ source_set("qtwebengine_sources") { deps = [ "//build:branding_buildflags", + "//chrome/browser/resources/quota_internals:quota_internals_resources", "//chrome/common:buildflags", "//components/nacl/common:buildflags", + "//components/performance_manager", + "//components/plugins/renderer/", "//extensions/buildflags:buildflags", + "//qtwebengine/common:mojo_bindings", + "//rlz/buildflags:buildflags", "//third_party/blink/public/mojom:mojom_platform", ] @@ -60,13 +65,23 @@ source_set("qtwebengine_sources") { "//chrome/browser/custom_handlers/protocol_handler_registry.h", "//chrome/browser/custom_handlers/protocol_handler_registry_factory.cc", "//chrome/browser/custom_handlers/protocol_handler_registry_factory.h", + "//chrome/browser/devtools/devtools_eye_dropper.cc", + "//chrome/browser/devtools/devtools_eye_dropper.h", "//chrome/browser/media/webrtc/desktop_media_list.h", "//chrome/browser/net/chrome_mojo_proxy_resolver_factory.cc", "//chrome/browser/net/chrome_mojo_proxy_resolver_factory.h", + "//chrome/browser/prefs/chrome_command_line_pref_store.cc", + "//chrome/browser/prefs/chrome_command_line_pref_store.h", "//chrome/browser/profiles/profile.cc", "//chrome/browser/profiles/profile.h", + "//chrome/browser/tab_contents/form_interaction_tab_helper.cc", + "//chrome/browser/tab_contents/form_interaction_tab_helper.h", "//chrome/browser/ui/webui/devtools_ui.cc", "//chrome/browser/ui/webui/devtools_ui.h", + "//chrome/browser/ui/webui/devtools_ui_data_source.cc", + "//chrome/browser/ui/webui/devtools_ui_data_source.h", + "//chrome/browser/ui/webui/net_internals/net_internals_ui.cc", + "//chrome/browser/ui/webui/net_internals/net_internals_ui.h", "//chrome/browser/ui/webui/quota_internals/quota_internals_handler.cc", "//chrome/browser/ui/webui/quota_internals/quota_internals_handler.h", "//chrome/browser/ui/webui/quota_internals/quota_internals_proxy.cc", @@ -75,6 +90,12 @@ source_set("qtwebengine_sources") { "//chrome/browser/ui/webui/quota_internals/quota_internals_types.h", "//chrome/browser/ui/webui/quota_internals/quota_internals_ui.cc", "//chrome/browser/ui/webui/quota_internals/quota_internals_ui.h", + "//chrome/browser/ui/webui/user_actions/user_actions_ui.cc", + "//chrome/browser/ui/webui/user_actions/user_actions_ui.h", + "//chrome/browser/ui/webui/user_actions/user_actions_ui_handler.cc", + "//chrome/browser/ui/webui/user_actions/user_actions_ui_handler.h", + "//chrome/browser/ui/webui/webui_util.cc", + "//chrome/browser/ui/webui/webui_util.h", "//chrome/common/custom_handlers/protocol_handler.cc", "//chrome/common/custom_handlers/protocol_handler.h", "//chrome/common/chrome_switches.cc", @@ -91,8 +112,10 @@ source_set("qtwebengine_sources") { deps += [ ":qtwebengine_extensions_features", "//chrome/app:generated_resources", + "//chrome/browser/extensions/api:api_registration", "//chrome/browser/resources:component_extension_resources_grit", "//chrome/common/extensions/api", + "//chrome/common/extensions/api:api", "//chrome/common/extensions/api:extensions_features", "//components/crx_file", "//components/crx_file:crx_creator", @@ -107,8 +130,12 @@ source_set("qtwebengine_sources") { "//extensions/renderer", "//extensions:extensions_resources", "//extensions/strings", + "//qtwebengine/browser/extensions/api:api_registration", + "//qtwebengine/common/extensions/api:api", ] sources += [ + "//chrome/browser/extensions/api/enterprise_hardware_platform/enterprise_hardware_platform_api.cc", + "//chrome/browser/extensions/api/enterprise_hardware_platform/enterprise_hardware_platform_api.h", "//chrome/common/extensions/permissions/chrome_api_permissions.cc", "//chrome/common/extensions/permissions/chrome_api_permissions.h", "//chrome/common/extensions/permissions/chrome_permission_message_provider.cc", @@ -128,8 +155,8 @@ source_set("qtwebengine_sources") { if (is_linux) { sources += [ - "//chrome/browser/ui/webui/sandbox_internals_ui.cc", - "//chrome/browser/ui/webui/sandbox_internals_ui.h", + "//chrome/browser/ui/webui/sandbox/sandbox_internals_ui.cc", + "//chrome/browser/ui/webui/sandbox/sandbox_internals_ui.h", ] } @@ -171,11 +198,65 @@ source_set("qtwebengine_sources") { deps += [ "//pdf", "//pdf:buildflags", + "//pdf:pdf_ppapi", "//components/pdf/browser:browser", "//components/pdf/renderer:renderer", "//components/printing/browser", - "//components/printing/renderer", + "//components/printing/renderer" + ] + sources += [ + "//chrome/browser/extensions/api/streams_private/streams_private_api.cc", ] } + + if (enable_webrtc && enable_extensions) { + deps += [ + "//chrome/browser/resources/media:webrtc_logs_resources", + "//components/upload_list", + "//components/webrtc_logging/browser", + "//components/webrtc_logging/common", + ] + + sources += [ + "//chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc", + "//chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h", + "//chrome/browser/media/webrtc/audio_debug_recordings_handler.cc", + "//chrome/browser/media/webrtc/audio_debug_recordings_handler.h", + "//chrome/browser/media/webrtc/webrtc_event_log_history.cc", + "//chrome/browser/media/webrtc/webrtc_event_log_history.h", + "//chrome/browser/media/webrtc/webrtc_event_log_manager.cc", + "//chrome/browser/media/webrtc/webrtc_event_log_manager.h", + "//chrome/browser/media/webrtc/webrtc_event_log_manager_common.cc", + "//chrome/browser/media/webrtc/webrtc_event_log_manager_common.h", + "//chrome/browser/media/webrtc/webrtc_event_log_manager_local.cc", + "//chrome/browser/media/webrtc/webrtc_event_log_manager_local.h", + "//chrome/browser/media/webrtc/webrtc_event_log_manager_remote.cc", + "//chrome/browser/media/webrtc/webrtc_event_log_manager_remote.h", + "//chrome/browser/media/webrtc/webrtc_event_log_uploader.cc", + "//chrome/browser/media/webrtc/webrtc_event_log_uploader.h", + "//chrome/browser/media/webrtc/webrtc_log_buffer.cc", + "//chrome/browser/media/webrtc/webrtc_log_buffer.h", + "//chrome/browser/media/webrtc/webrtc_log_uploader.cc", + "//chrome/browser/media/webrtc/webrtc_log_uploader.h", + "//chrome/browser/media/webrtc/webrtc_logging_controller.cc", + "//chrome/browser/media/webrtc/webrtc_logging_controller.h", + "//chrome/browser/media/webrtc/webrtc_rtp_dump_handler.cc", + "//chrome/browser/media/webrtc/webrtc_rtp_dump_handler.h", + "//chrome/browser/media/webrtc/webrtc_rtp_dump_writer.cc", + "//chrome/browser/media/webrtc/webrtc_rtp_dump_writer.h", + "//chrome/browser/media/webrtc/webrtc_text_log_handler.cc", + "//chrome/browser/media/webrtc/webrtc_text_log_handler.h", + "//chrome/browser/ui/webui/media/webrtc_logs_ui.cc", + "//chrome/browser/ui/webui/media/webrtc_logs_ui.h", + "//chrome/renderer/media/webrtc_logging_agent_impl.cc", + "//chrome/renderer/media/webrtc_logging_agent_impl.h", + ] + } } +if (is_win) { + shared_library("qtwebengine_sandbox_win") { + create_pri_file = true + public_deps = [ "//sandbox/win:sandbox" ] + } +} diff --git a/src/core/quota_permission_context_qt.cpp b/src/core/quota_permission_context_qt.cpp index a502e7fc8..549414d33 100644 --- a/src/core/quota_permission_context_qt.cpp +++ b/src/core/quota_permission_context_qt.cpp @@ -56,55 +56,65 @@ using content::WebContents; namespace QtWebEngineCore { -void QuotaPermissionContextQt::RequestQuotaPermission(const StorageQuotaParams ¶ms, int render_process_id, const PermissionCallback &callback) +void QuotaPermissionContextQt::RequestQuotaPermission(const StorageQuotaParams ¶ms, int render_process_id, PermissionCallback callback) { if (params.storage_type != blink::mojom::StorageType::kPersistent) { // For now we only support requesting quota with this interface // for Persistent storage type. - callback.Run(QUOTA_PERMISSION_RESPONSE_DISALLOW); + dispatchCallbackOnIOThread(std::move(callback), QUOTA_PERMISSION_RESPONSE_DISALLOW); return; } if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) { - base::PostTaskWithTraits( + base::PostTask( FROM_HERE, {content::BrowserThread::UI}, base::BindOnce(&QuotaPermissionContextQt::RequestQuotaPermission, this, - params, render_process_id, callback)); + params, render_process_id, std::move(callback))); return; } RenderFrameHost *renderFrameHost = RenderFrameHost::FromID(render_process_id, params.render_frame_id); - if (!renderFrameHost) + if (!renderFrameHost) { + LOG(WARNING) << "Attempt to request quota from frameless renderer: " + << render_process_id << "," << params.render_frame_id; + dispatchCallbackOnIOThread(std::move(callback), QUOTA_PERMISSION_RESPONSE_CANCELLED); return; + } WebContents *webContents = WebContents::FromRenderFrameHost(renderFrameHost); - if (!webContents) + if (!webContents) { + LOG(ERROR) << "Attempt to request quota from frame missing webcontents"; + dispatchCallbackOnIOThread(std::move(callback), QUOTA_PERMISSION_RESPONSE_CANCELLED); return; + } WebContentsAdapterClient *client = WebContentsViewQt::from(static_cast<content::WebContentsImpl *>(webContents)->GetView())->client(); - if (!client) + if (!client) { + LOG(ERROR) << "Attempt to request quota from content missing webcontents client"; + dispatchCallbackOnIOThread(std::move(callback), QUOTA_PERMISSION_RESPONSE_CANCELLED); return; + } QWebEngineQuotaRequest request( - QSharedPointer<QuotaRequestControllerImpl>::create(this, params, callback)); + QSharedPointer<QuotaRequestControllerImpl>::create(this, params, std::move(callback))); client->runQuotaRequest(std::move(request)); } -void QuotaPermissionContextQt::dispatchCallbackOnIOThread(const PermissionCallback &callback, +void QuotaPermissionContextQt::dispatchCallbackOnIOThread(PermissionCallback callback, QuotaPermissionContext::QuotaPermissionResponse response) { if (callback.is_null()) return; if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)) { - base::PostTaskWithTraits( + base::PostTask( FROM_HERE, {content::BrowserThread::IO}, base::BindOnce(&QuotaPermissionContextQt::dispatchCallbackOnIOThread, - this, callback, response)); + this, std::move(callback), response)); return; } - callback.Run(response); + std::move(callback).Run(response); } } // namespace QtWebEngineCore diff --git a/src/core/quota_permission_context_qt.h b/src/core/quota_permission_context_qt.h index 99e07eec7..528928c1a 100644 --- a/src/core/quota_permission_context_qt.h +++ b/src/core/quota_permission_context_qt.h @@ -42,17 +42,15 @@ #include "content/public/browser/quota_permission_context.h" -#include <QtCore/qcompilerdetection.h> // Needed for override - namespace QtWebEngineCore { class QuotaPermissionContextQt : public content::QuotaPermissionContext { public: void RequestQuotaPermission(const content::StorageQuotaParams ¶ms, int render_process_id, - const PermissionCallback &callback) override; + PermissionCallback callback) override; - void dispatchCallbackOnIOThread(const PermissionCallback &callback, + void dispatchCallbackOnIOThread(PermissionCallback callback, QuotaPermissionContext::QuotaPermissionResponse response); }; diff --git a/src/core/quota_request_controller_impl.cpp b/src/core/quota_request_controller_impl.cpp index a18ad761d..ea2526d45 100644 --- a/src/core/quota_request_controller_impl.cpp +++ b/src/core/quota_request_controller_impl.cpp @@ -43,30 +43,30 @@ namespace QtWebEngineCore { -QuotaRequestControllerImpl::QuotaRequestControllerImpl( - QuotaPermissionContextQt *context, +QuotaRequestControllerImpl::QuotaRequestControllerImpl(QuotaPermissionContextQt *context, const content::StorageQuotaParams ¶ms, - const content::QuotaPermissionContext::PermissionCallback &callback) + content::QuotaPermissionContext::PermissionCallback callback) : QuotaRequestController( toQt(params.origin_url), params.requested_size) , m_context(context) - , m_callback(callback) + , m_callback(std::move(callback)) {} QuotaRequestControllerImpl::~QuotaRequestControllerImpl() { - reject(); + if (m_callback) + m_context->dispatchCallbackOnIOThread(std::move(m_callback), content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_CANCELLED); } void QuotaRequestControllerImpl::accepted() { - m_context->dispatchCallbackOnIOThread(m_callback, QuotaPermissionContextQt::QUOTA_PERMISSION_RESPONSE_ALLOW); + m_context->dispatchCallbackOnIOThread(std::move(m_callback), content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_ALLOW); } void QuotaRequestControllerImpl::rejected() { - m_context->dispatchCallbackOnIOThread(m_callback, QuotaPermissionContextQt::QUOTA_PERMISSION_RESPONSE_DISALLOW); + m_context->dispatchCallbackOnIOThread(std::move(m_callback), content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_DISALLOW); } } // namespace QtWebEngineCore diff --git a/src/core/quota_request_controller_impl.h b/src/core/quota_request_controller_impl.h index 5814895f3..65e661694 100644 --- a/src/core/quota_request_controller_impl.h +++ b/src/core/quota_request_controller_impl.h @@ -50,7 +50,7 @@ public: QuotaRequestControllerImpl( QuotaPermissionContextQt *context, const content::StorageQuotaParams ¶ms, - const content::QuotaPermissionContext::PermissionCallback &callback); + content::QuotaPermissionContext::PermissionCallback callback); ~QuotaRequestControllerImpl(); diff --git a/src/core/render_view_context_menu_qt.cpp b/src/core/render_view_context_menu_qt.cpp index 4e182973c..8fdae498c 100644 --- a/src/core/render_view_context_menu_qt.cpp +++ b/src/core/render_view_context_menu_qt.cpp @@ -98,6 +98,8 @@ namespace QtWebEngineCore { appendCopyItem(); else appendPageItems(); + } else { + appendPageItems(); } if (m_contextData.linkUrl().isValid() || !m_contextData.unfilteredLinkUrl().isEmpty() || !m_contextData.linkUrl().isEmpty()) diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index 15cc5174e..7acef2b15 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -1,3 +1,4 @@ + /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. @@ -41,13 +42,13 @@ #include "browser_accessibility_manager_qt.h" #include "common/qt_messages.h" -#include "compositor/compositor.h" #include "qtwebenginecoreglobal_p.h" #include "render_widget_host_view_qt_delegate.h" #include "touch_handle_drawable_client.h" #include "touch_selection_controller_client_qt.h" #include "touch_selection_menu_controller.h" #include "type_conversion.h" +#include "web_contents_adapter.h" #include "web_contents_adapter_client.h" #include "web_event_factory.h" @@ -56,23 +57,30 @@ #include "components/viz/common/frame_sinks/begin_frame_source.h" #include "components/viz/common/surfaces/frame_sink_id_allocator.h" #include "components/viz/host/host_frame_sink_manager.h" +#include "content/browser/compositor/image_transport_factory.h" #include "content/browser/compositor/surface_utils.h" -#include "content/browser/frame_host/frame_tree.h" -#include "content/browser/frame_host/render_frame_host_impl.h" +#include "content/browser/renderer_host/display_util.h" +#include "content/browser/renderer_host/frame_tree.h" +#include "content/browser/renderer_host/frame_tree_node.h" +#include "content/browser/renderer_host/cursor_manager.h" #include "content/browser/renderer_host/input/synthetic_gesture_target.h" +#include "content/browser/renderer_host/render_frame_host_impl.h" #include "content/browser/renderer_host/render_view_host_delegate.h" #include "content/browser/renderer_host/render_view_host_impl.h" -#include "content/common/content_switches_internal.h" #include "content/browser/renderer_host/render_widget_host_input_event_router.h" +#include "content/browser/renderer_host/ui_events_helper.h" +#include "content/common/content_switches_internal.h" #include "content/common/cursors/webcursor.h" #include "content/common/input_messages.h" #include "third_party/skia/include/core/SkColor.h" -#include "third_party/blink/public/platform/web_cursor_info.h" +#include "ui/base/cursor/cursor.h" +#include "ui/base/resource/resource_bundle.h" #include "ui/events/blink/blink_event_util.h" #include "ui/events/event.h" #include "ui/events/gesture_detection/gesture_configuration.h" #include "ui/events/gesture_detection/gesture_provider_config_helper.h" #include "ui/events/gesture_detection/motion_event.h" +#include "ui/events/keycodes/dom/dom_keyboard_layout_map.h" #include "ui/gfx/image/image_skia.h" #include "ui/touch_selection/touch_selection_controller.h" @@ -81,9 +89,12 @@ #endif #if defined(USE_AURA) -#include "ui/base/cursor/cursor.h" +#include "ui/base/cursor/cursor_size.h" #include "ui/base/cursor/cursors_aura.h" -#include "ui/base/resource/resource_bundle.h" +#endif + +#if defined(Q_OS_MACOS) +#include "content/app/resources/grit/content_resources.h" #endif #include <private/qguiapplication_p.h> @@ -97,6 +108,7 @@ #include <QKeyEvent> #include <QMouseEvent> #include <QPixmap> +#include <QScopeGuard> #include <QScreen> #include <QStyleHints> #include <QVariant> @@ -178,12 +190,6 @@ static inline ui::GestureProvider::Config QtGestureProviderConfig() { return config; } -static inline bool compareTouchPoints(const QTouchEvent::TouchPoint &lhs, const QTouchEvent::TouchPoint &rhs) -{ - // TouchPointPressed < TouchPointMoved < TouchPointReleased - return lhs.state() < rhs.state(); -} - static inline bool isCommonTextEditShortcut(const QKeyEvent *ke) { return QInputControl::isCommonTextEditShortcut(ke); @@ -192,43 +198,48 @@ static inline bool isCommonTextEditShortcut(const QKeyEvent *ke) static uint32_t s_eventId = 0; class MotionEventQt : public ui::MotionEvent { public: - MotionEventQt(const QList<QTouchEvent::TouchPoint> &touchPoints, const base::TimeTicks &eventTime, Action action, const Qt::KeyboardModifiers modifiers, int index = -1) - : touchPoints(touchPoints) + MotionEventQt(const QList<QPair<int, QTouchEvent::TouchPoint>> &points, const base::TimeTicks &eventTime, + Action action, const Qt::KeyboardModifiers modifiers, int index = -1) + : touchPoints(points) , eventTime(eventTime) , action(action) , eventId(++s_eventId) , flags(flagsFromModifiers(modifiers)) , index(index) { - // ACTION_DOWN and ACTION_UP must be accesssed through pointer_index 0 - Q_ASSERT((action != Action::DOWN && action != Action::UP) || index == 0); + // index is only valid for ACTION_DOWN and ACTION_UP and should correspond to the point causing it + // see blink_event_util.cc:ToWebTouchPointState for details + Q_ASSERT_X((action != Action::POINTER_DOWN && action != Action::POINTER_UP && index == -1) + || (action == Action::POINTER_DOWN && index >= 0 && touchPoint(index).state() == Qt::TouchPointPressed) + || (action == Action::POINTER_UP && index >= 0 && touchPoint(index).state() == Qt::TouchPointReleased), + "MotionEventQt", qPrintable(QString("action: %1, index: %2, state: %3").arg(int(action)).arg(index).arg(touchPoint(index).state()))); } uint32_t GetUniqueEventId() const override { return eventId; } Action GetAction() const override { return action; } int GetActionIndex() const override { return index; } size_t GetPointerCount() const override { return touchPoints.size(); } - int GetPointerId(size_t pointer_index) const override { return touchPoints.at(pointer_index).id(); } - float GetX(size_t pointer_index) const override { return touchPoints.at(pointer_index).pos().x(); } - float GetY(size_t pointer_index) const override { return touchPoints.at(pointer_index).pos().y(); } - float GetRawX(size_t pointer_index) const override { return touchPoints.at(pointer_index).screenPos().x(); } - float GetRawY(size_t pointer_index) const override { return touchPoints.at(pointer_index).screenPos().y(); } + int GetPointerId(size_t pointer_index) const override { return touchPoints[pointer_index].first; } + float GetX(size_t pointer_index) const override { return touchPoint(pointer_index).pos().x(); } + float GetY(size_t pointer_index) const override { return touchPoint(pointer_index).pos().y(); } + float GetRawX(size_t pointer_index) const override { return touchPoint(pointer_index).screenPos().x(); } + float GetRawY(size_t pointer_index) const override { return touchPoint(pointer_index).screenPos().y(); } float GetTouchMajor(size_t pointer_index) const override { - QRectF touchRect = touchPoints.at(pointer_index).rect(); - return std::max(touchRect.height(), touchRect.width()); + QSizeF diams = touchPoint(pointer_index).ellipseDiameters(); + return std::max(diams.height(), diams.width()); } float GetTouchMinor(size_t pointer_index) const override { - QRectF touchRect = touchPoints.at(pointer_index).rect(); - return std::min(touchRect.height(), touchRect.width()); + QSizeF diams = touchPoint(pointer_index).ellipseDiameters(); + return std::min(diams.height(), diams.width()); } float GetOrientation(size_t pointer_index) const override { return 0; } int GetFlags() const override { return flags; } - float GetPressure(size_t pointer_index) const override { return touchPoints.at(pointer_index).pressure(); } + float GetPressure(size_t pointer_index) const override { return touchPoint(pointer_index).pressure(); } float GetTiltX(size_t pointer_index) const override { return 0; } float GetTiltY(size_t pointer_index) const override { return 0; } float GetTwist(size_t) const override { return 0; } @@ -241,49 +252,97 @@ public: float GetHistoricalX(size_t pointer_index, size_t historical_index) const override { return 0; } float GetHistoricalY(size_t pointer_index, size_t historical_index) const override { return 0; } ToolType GetToolType(size_t pointer_index) const override { - return (touchPoints.at(pointer_index).flags() & QTouchEvent::TouchPoint::InfoFlag::Pen) ? ui::MotionEvent::ToolType::STYLUS - : ui::MotionEvent::ToolType::FINGER; + bool isPen = touchPoint(pointer_index).flags() & QTouchEvent::TouchPoint::InfoFlag::Pen; + return isPen ? ui::MotionEvent::ToolType::STYLUS : ui::MotionEvent::ToolType::FINGER; } int GetButtonState() const override { return 0; } private: - QList<QTouchEvent::TouchPoint> touchPoints; + QList<QPair<int, QTouchEvent::TouchPoint>> touchPoints; base::TimeTicks eventTime; Action action; const uint32_t eventId; int flags; int index; + const QTouchEvent::TouchPoint& touchPoint(size_t i) const { return touchPoints[i].second; } }; -static content::ScreenInfo screenInfoFromQScreen(QScreen *screen) +extern display::Display toDisplayDisplay(int id, const QScreen *screen); + +static blink::ScreenInfo screenInfoFromQScreen(QScreen *screen) { - content::ScreenInfo r; - if (screen) { - r.device_scale_factor = screen->devicePixelRatio(); - r.depth_per_component = 8; - r.depth = screen->depth(); - r.is_monochrome = (r.depth == 1); - r.rect = toGfx(screen->geometry()); - r.available_rect = toGfx(screen->availableGeometry()); - } else { + blink::ScreenInfo r; + if (!screen) + screen = qApp->primaryScreen(); + if (screen) + content::DisplayUtil::DisplayToScreenInfo(&r, toDisplayDisplay(0, screen)); + else r.device_scale_factor = qGuiApp->devicePixelRatio(); - } return r; } +// An minimal override to support progressing flings +class FlingingCompositor : public ui::Compositor +{ + RenderWidgetHostViewQt *m_rwhv; +public: + FlingingCompositor(RenderWidgetHostViewQt *rwhv, + const viz::FrameSinkId &frame_sink_id, + ui::ContextFactory *context_factory, + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + bool enable_pixel_canvas, + bool use_external_begin_frame_control = false, + bool force_software_compositor = false) + : ui::Compositor(frame_sink_id, context_factory, + task_runner, enable_pixel_canvas, + use_external_begin_frame_control, + force_software_compositor) + , m_rwhv(rwhv) + {} + + void BeginMainFrame(const viz::BeginFrameArgs &args) override + { + if (args.type != viz::BeginFrameArgs::MISSED && !m_rwhv->is_currently_scrolling_viewport()) + m_rwhv->host()->ProgressFlingIfNeeded(args.frame_time); + ui::Compositor::BeginMainFrame(args); + } +}; + +class GuestInputEventObserverQt : public content::RenderWidgetHost::InputEventObserver +{ +public: + GuestInputEventObserverQt(RenderWidgetHostViewQt *rwhv) + : m_rwhv(rwhv) + { + } + ~GuestInputEventObserverQt() {} + + void OnInputEvent(const blink::WebInputEvent&) override {} + void OnInputEventAck(blink::mojom::InputEventResultSource, + blink::mojom::InputEventResultState state, + const blink::WebInputEvent &event) override + { + if (event.GetType() == blink::WebInputEvent::Type::kMouseWheel) + m_rwhv->WheelEventAck(static_cast<const blink::WebMouseWheelEvent &>(event), state); + } + +private: + RenderWidgetHostViewQt *m_rwhv; +}; + RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget) : content::RenderWidgetHostViewBase::RenderWidgetHostViewBase(widget) , m_taskRunner(base::ThreadTaskRunnerHandle::Get()) , m_gestureProvider(QtGestureProviderConfig(), this) , m_sendMotionActionDown(false) , m_touchMotionStarted(false) - , m_enableViz(features::IsVizDisplayCompositorEnabled()) + , m_guestInputEventObserver(new GuestInputEventObserverQt(this)) , m_visible(false) - , m_needsBeginFrames(false) , m_loadVisuallyCommittedState(NotCommitted) , m_adapterClient(0) , m_imeInProgress(false) , m_receivedEmptyImeEvent(false) + , m_isMouseLocked(false) , m_imState(0) , m_anchorPositionWithinSelection(-1) , m_cursorPositionWithinSelection(-1) @@ -299,36 +358,33 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget const QPlatformInputContext *context = QGuiApplicationPrivate::platformIntegration()->inputContext(); m_imeHasHiddenTextCapability = context && context->hasCapability(QPlatformInputContext::HiddenTextCapability); - if (m_enableViz) { - m_rootLayer.reset(new ui::Layer(ui::LAYER_SOLID_COLOR)); - m_rootLayer->SetColor(SK_ColorTRANSPARENT); - - m_delegatedFrameHost.reset(new content::DelegatedFrameHost( - host()->GetFrameSinkId(), - &m_delegatedFrameHostClient, - true /* should_register_frame_sink_id */)); - - content::ImageTransportFactory *imageTransportFactory = content::ImageTransportFactory::GetInstance(); - ui::ContextFactory *contextFactory = imageTransportFactory->GetContextFactory(); - ui::ContextFactoryPrivate *contextFactoryPrivate = imageTransportFactory->GetContextFactoryPrivate(); - m_uiCompositor.reset(new ui::Compositor( - contextFactoryPrivate->AllocateFrameSinkId(), - contextFactory, - contextFactoryPrivate, - m_taskRunner, - false /* enable_pixel_canvas */)); - m_uiCompositor->SetAcceleratedWidget(gfx::kNullAcceleratedWidget); // null means offscreen - m_uiCompositor->SetRootLayer(m_rootLayer.get()); - - m_displayFrameSink = DisplayFrameSink::findOrCreate(m_uiCompositor->frame_sink_id()); - m_displayFrameSink->connect(this); - } else { - m_compositor.reset(new Compositor(widget)); - } + m_rootLayer.reset(new ui::Layer(ui::LAYER_SOLID_COLOR)); + m_rootLayer->SetColor(SK_ColorTRANSPARENT); + + m_delegatedFrameHost.reset(new content::DelegatedFrameHost( + host()->GetFrameSinkId(), + &m_delegatedFrameHostClient, + true /* should_register_frame_sink_id */)); + + content::ImageTransportFactory *imageTransportFactory = content::ImageTransportFactory::GetInstance(); + ui::ContextFactory *contextFactory = imageTransportFactory->GetContextFactory(); + m_uiCompositor.reset(new FlingingCompositor( + this, + contextFactory->AllocateFrameSinkId(), + contextFactory, + m_taskRunner, + false /* enable_pixel_canvas */)); + m_uiCompositor->SetAcceleratedWidget(gfx::kNullAcceleratedWidget); // null means offscreen + m_uiCompositor->SetRootLayer(m_rootLayer.get()); + + m_displayFrameSink = DisplayFrameSink::findOrCreate(m_uiCompositor->frame_sink_id()); + m_displayFrameSink->connect(this); if (host()->delegate() && host()->delegate()->GetInputEventRouter()) host()->delegate()->GetInputEventRouter()->AddFrameSinkIdOwner(GetFrameSinkId(), this); + m_cursorManager.reset(new content::CursorManager(this)); + m_touchSelectionControllerClient.reset(new TouchSelectionControllerClientQt(this)); ui::TouchSelectionController::Config config; config.max_tap_duration = base::TimeDelta::FromMilliseconds(ui::GestureConfiguration::GetInstance()->long_press_time_in_ms()); @@ -336,9 +392,9 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget config.enable_longpress_drag_selection = false; m_touchSelectionController.reset(new ui::TouchSelectionController(m_touchSelectionControllerClient.get(), config)); + host()->render_frame_metadata_provider()->AddObserver(this); host()->render_frame_metadata_provider()->ReportAllFrameSubmissionsForTesting(true); - // May call SetNeedsBeginFrames host()->SetView(this); } @@ -348,19 +404,25 @@ RenderWidgetHostViewQt::~RenderWidgetHostViewQt() QObject::disconnect(m_adapterClientDestroyedConnection); - if (m_enableViz) - m_displayFrameSink->disconnect(this); + m_displayFrameSink->disconnect(this); if (text_input_manager_) text_input_manager_->RemoveObserver(this); m_touchSelectionController.reset(); m_touchSelectionControllerClient.reset(); + + host()->render_frame_metadata_provider()->RemoveObserver(this); + host()->ViewDestroyed(); } void RenderWidgetHostViewQt::setDelegate(RenderWidgetHostViewQtDelegate* delegate) { m_delegate.reset(delegate); + if (m_deferredShow) { + m_deferredShow = false; + Show(); + } visualPropertiesChanged(); } @@ -375,6 +437,11 @@ void RenderWidgetHostViewQt::setAdapterClient(WebContentsAdapterClient *adapterC m_adapterClient = nullptr; }); } +void RenderWidgetHostViewQt::setGuest(content::RenderWidgetHostImpl *rwh) +{ + rwh->AddInputEventObserver(m_guestInputEventObserver.get()); +} + void RenderWidgetHostViewQt::InitAsChild(gfx::NativeView) { } @@ -390,6 +457,9 @@ void RenderWidgetHostViewQt::InitAsFullscreen(content::RenderWidgetHostView*) void RenderWidgetHostViewQt::SetSize(const gfx::Size &sizeInDips) { + if (!m_delegate) + return; + m_delegate->resize(sizeInDips.width(), sizeInDips.height()); } @@ -419,14 +489,14 @@ gfx::NativeViewAccessible RenderWidgetHostViewQt::GetNativeViewAccessible() content::BrowserAccessibilityManager* RenderWidgetHostViewQt::CreateBrowserAccessibilityManager(content::BrowserAccessibilityDelegate* delegate, bool for_root_frame) { Q_UNUSED(for_root_frame); // FIXME -#ifndef QT_NO_ACCESSIBILITY +#if QT_CONFIG(accessibility) return new content::BrowserAccessibilityManagerQt( m_adapterClient->accessibilityParentObject(), content::BrowserAccessibilityManagerQt::GetEmptyDocument(), delegate); #else return 0; -#endif // QT_NO_ACCESSIBILITY +#endif // QT_CONFIG(accessibility) } // Set focus to the associated View component. @@ -442,41 +512,45 @@ bool RenderWidgetHostViewQt::HasFocus() return m_delegate->hasKeyboardFocus(); } +bool RenderWidgetHostViewQt::IsMouseLocked() +{ + return m_isMouseLocked; +} + +viz::FrameSinkId RenderWidgetHostViewQt::GetRootFrameSinkId() +{ + return m_uiCompositor->frame_sink_id(); +} + bool RenderWidgetHostViewQt::IsSurfaceAvailableForCopy() { - if (m_enableViz) - return m_delegatedFrameHost->CanCopyFromCompositingSurface(); - return true; + return m_delegatedFrameHost->CanCopyFromCompositingSurface(); } void RenderWidgetHostViewQt::CopyFromSurface(const gfx::Rect &src_rect, const gfx::Size &output_size, base::OnceCallback<void(const SkBitmap &)> callback) { - if (m_enableViz) { - m_delegatedFrameHost->CopyFromCompositingSurface(src_rect, output_size, std::move(callback)); - return; - } - - QImage image; - if (m_delegate->copySurface(toQt(src_rect), toQt(output_size), image)) - std::move(callback).Run(toSkBitmap(image)); - else - std::move(callback).Run(SkBitmap()); + m_delegatedFrameHost->CopyFromCompositingSurface(src_rect, output_size, std::move(callback)); } void RenderWidgetHostViewQt::Show() { - m_delegate->show(); + if (m_delegate) + m_delegate->show(); + else + m_deferredShow = true; } void RenderWidgetHostViewQt::Hide() { + Q_ASSERT(m_delegate); m_delegate->hide(); } bool RenderWidgetHostViewQt::IsShowing() { + Q_ASSERT(m_delegate); return m_delegate->isVisible(); } @@ -488,41 +562,117 @@ gfx::Rect RenderWidgetHostViewQt::GetViewBounds() void RenderWidgetHostViewQt::UpdateBackgroundColor() { - if (m_enableViz) { - DCHECK(GetBackgroundColor()); - SkColor color = *GetBackgroundColor(); - bool opaque = SkColorGetA(color) == SK_AlphaOPAQUE; - m_rootLayer->SetFillsBoundsOpaquely(opaque); - m_rootLayer->SetColor(color); - m_uiCompositor->SetBackgroundColor(color); - m_delegate->setClearColor(toQt(color)); - host()->Send(new RenderViewObserverQt_SetBackgroundColor(host()->GetRoutingID(), color)); - return; - } + DCHECK(GetBackgroundColor()); + SkColor color = *GetBackgroundColor(); - auto color = GetBackgroundColor(); - if (color) { - m_delegate->setClearColor(toQt(*color)); - host()->Send(new RenderViewObserverQt_SetBackgroundColor(host()->GetRoutingID(), *color)); - } + m_delegate->setClearColor(toQt(color)); + + bool opaque = SkColorGetA(color) == SK_AlphaOPAQUE; + m_rootLayer->SetFillsBoundsOpaquely(opaque); + m_rootLayer->SetColor(color); + m_uiCompositor->SetBackgroundColor(color); + + content::RenderViewHost *rvh = content::RenderViewHost::From(host()); + if (color == SK_ColorTRANSPARENT) + host()->owner_delegate()->SetBackgroundOpaque(false); } // Return value indicates whether the mouse is locked successfully or not. -bool RenderWidgetHostViewQt::LockMouse() +blink::mojom::PointerLockResult RenderWidgetHostViewQt::LockMouse(bool request_unadjusted_movement) { + if (request_unadjusted_movement) + return blink::mojom::PointerLockResult::kUnsupportedOptions; + m_previousMousePosition = QCursor::pos(); m_delegate->lockMouse(); + m_isMouseLocked = true; qApp->setOverrideCursor(Qt::BlankCursor); - return true; + return blink::mojom::PointerLockResult::kSuccess; +} + +blink::mojom::PointerLockResult RenderWidgetHostViewQt::ChangeMouseLock(bool request_unadjusted_movement) +{ + if (request_unadjusted_movement) + return blink::mojom::PointerLockResult::kUnsupportedOptions; + return blink::mojom::PointerLockResult::kSuccess; } void RenderWidgetHostViewQt::UnlockMouse() { m_delegate->unlockMouse(); qApp->restoreOverrideCursor(); + m_isMouseLocked = false; host()->LostMouseLock(); } +bool RenderWidgetHostViewQt::updateCursorFromResource(ui::mojom::CursorType type) +{ + int resourceId; + // GetCursorDataFor only knows hotspots for 1x and 2x cursor images, in physical pixels. + qreal hotspotDpr = m_screenInfo.device_scale_factor <= 1.0f ? 1.0f : 2.0f; + qreal hotX; + qreal hotY; + +#if defined(USE_AURA) + gfx::Point hotspot; + if (!ui::GetCursorDataFor(ui::CursorSize::kNormal, type, hotspotDpr, &resourceId, &hotspot)) + return false; + hotX = hotspot.x(); + hotY = hotspot.y(); +#elif defined(Q_OS_MACOS) + // See chromium/content/common/cursors/webcursor_mac.mm + switch (type) { + case ui::mojom::CursorType::kVerticalText: + // TODO: [NSCursor IBeamCursorForVerticalLayout] + return false; + case ui::mojom::CursorType::kCell: + resourceId = IDR_CELL_CURSOR; + hotX = 7; + hotY = 7; + break; + case ui::mojom::CursorType::kContextMenu: + // TODO: [NSCursor contextualMenuCursor] + return false; + case ui::mojom::CursorType::kZoomIn: + resourceId = IDR_ZOOMIN_CURSOR; + hotX = 7; + hotY = 7; + break; + case ui::mojom::CursorType::kZoomOut: + resourceId = IDR_ZOOMOUT_CURSOR; + hotX = 7; + hotY = 7; + break; + default: + Q_UNREACHABLE(); + return false; + } +#else + Q_UNREACHABLE(); + return false; +#endif + + const gfx::ImageSkia *imageSkia = ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resourceId); + if (!imageSkia) + return false; + + QImage imageQt = toQImage(imageSkia->GetRepresentation(m_screenInfo.device_scale_factor)); + + // Convert hotspot coordinates into device-independent pixels. + hotX /= hotspotDpr; + hotY /= hotspotDpr; + +#if defined(Q_OS_LINUX) + // QTBUG-68571: On Linux (xcb, wayland, eglfs), hotspot coordinates must be in physical pixels. + qreal imageDpr = imageQt.devicePixelRatio(); + hotX *= imageDpr; + hotY *= imageDpr; +#endif + + m_delegate->updateCursor(QCursor(QPixmap::fromImage(std::move(imageQt)), qRound(hotX), qRound(hotY))); + return true; +} + void RenderWidgetHostViewQt::UpdateCursor(const content::WebCursor &webCursor) { DisplayCursor(webCursor); @@ -530,162 +680,120 @@ void RenderWidgetHostViewQt::UpdateCursor(const content::WebCursor &webCursor) void RenderWidgetHostViewQt::DisplayCursor(const content::WebCursor &webCursor) { - const content::CursorInfo &cursorInfo = webCursor.info(); + const ui::Cursor &cursorInfo = webCursor.cursor(); Qt::CursorShape shape = Qt::ArrowCursor; -#if defined(USE_AURA) - ui::CursorType auraType = ui::CursorType::kNull; -#endif - switch (cursorInfo.type) { - case ui::CursorType::kNull: - case ui::CursorType::kPointer: + switch (cursorInfo.type()) { + case ui::mojom::CursorType::kNull: + case ui::mojom::CursorType::kPointer: shape = Qt::ArrowCursor; break; - case ui::CursorType::kCross: + case ui::mojom::CursorType::kCross: shape = Qt::CrossCursor; break; - case ui::CursorType::kHand: + case ui::mojom::CursorType::kHand: shape = Qt::PointingHandCursor; break; - case ui::CursorType::kIBeam: + case ui::mojom::CursorType::kIBeam: shape = Qt::IBeamCursor; break; - case ui::CursorType::kWait: + case ui::mojom::CursorType::kWait: shape = Qt::WaitCursor; break; - case ui::CursorType::kHelp: + case ui::mojom::CursorType::kHelp: shape = Qt::WhatsThisCursor; break; - case ui::CursorType::kEastResize: - case ui::CursorType::kWestResize: - case ui::CursorType::kEastWestResize: - case ui::CursorType::kEastPanning: - case ui::CursorType::kWestPanning: - case ui::CursorType::kMiddlePanningHorizontal: + case ui::mojom::CursorType::kEastResize: + case ui::mojom::CursorType::kWestResize: + case ui::mojom::CursorType::kEastWestResize: + case ui::mojom::CursorType::kEastPanning: + case ui::mojom::CursorType::kWestPanning: + case ui::mojom::CursorType::kMiddlePanningHorizontal: shape = Qt::SizeHorCursor; break; - case ui::CursorType::kNorthResize: - case ui::CursorType::kSouthResize: - case ui::CursorType::kNorthSouthResize: - case ui::CursorType::kNorthPanning: - case ui::CursorType::kSouthPanning: - case ui::CursorType::kMiddlePanningVertical: + case ui::mojom::CursorType::kNorthResize: + case ui::mojom::CursorType::kSouthResize: + case ui::mojom::CursorType::kNorthSouthResize: + case ui::mojom::CursorType::kNorthPanning: + case ui::mojom::CursorType::kSouthPanning: + case ui::mojom::CursorType::kMiddlePanningVertical: shape = Qt::SizeVerCursor; break; - case ui::CursorType::kNorthEastResize: - case ui::CursorType::kSouthWestResize: - case ui::CursorType::kNorthEastSouthWestResize: - case ui::CursorType::kNorthEastPanning: - case ui::CursorType::kSouthWestPanning: + case ui::mojom::CursorType::kNorthEastResize: + case ui::mojom::CursorType::kSouthWestResize: + case ui::mojom::CursorType::kNorthEastSouthWestResize: + case ui::mojom::CursorType::kNorthEastPanning: + case ui::mojom::CursorType::kSouthWestPanning: shape = Qt::SizeBDiagCursor; break; - case ui::CursorType::kNorthWestResize: - case ui::CursorType::kSouthEastResize: - case ui::CursorType::kNorthWestSouthEastResize: - case ui::CursorType::kNorthWestPanning: - case ui::CursorType::kSouthEastPanning: + case ui::mojom::CursorType::kNorthWestResize: + case ui::mojom::CursorType::kSouthEastResize: + case ui::mojom::CursorType::kNorthWestSouthEastResize: + case ui::mojom::CursorType::kNorthWestPanning: + case ui::mojom::CursorType::kSouthEastPanning: shape = Qt::SizeFDiagCursor; break; - case ui::CursorType::kColumnResize: + case ui::mojom::CursorType::kColumnResize: shape = Qt::SplitHCursor; break; - case ui::CursorType::kRowResize: + case ui::mojom::CursorType::kRowResize: shape = Qt::SplitVCursor; break; - case ui::CursorType::kMiddlePanning: - case ui::CursorType::kMove: + case ui::mojom::CursorType::kMiddlePanning: + case ui::mojom::CursorType::kMove: shape = Qt::SizeAllCursor; break; - case ui::CursorType::kProgress: + case ui::mojom::CursorType::kProgress: shape = Qt::BusyCursor; break; - case ui::CursorType::kDndNone: - case ui::CursorType::kDndMove: + case ui::mojom::CursorType::kDndNone: + case ui::mojom::CursorType::kDndMove: shape = Qt::DragMoveCursor; break; - case ui::CursorType::kDndCopy: - case ui::CursorType::kCopy: + case ui::mojom::CursorType::kDndCopy: + case ui::mojom::CursorType::kCopy: shape = Qt::DragCopyCursor; break; - case ui::CursorType::kDndLink: - case ui::CursorType::kAlias: + case ui::mojom::CursorType::kDndLink: + case ui::mojom::CursorType::kAlias: shape = Qt::DragLinkCursor; break; -#if defined(USE_AURA) - case ui::CursorType::kVerticalText: - auraType = ui::CursorType::kVerticalText; - break; - case ui::CursorType::kCell: - auraType = ui::CursorType::kCell; - break; - case ui::CursorType::kContextMenu: - auraType = ui::CursorType::kContextMenu; - break; - case ui::CursorType::kZoomIn: - auraType = ui::CursorType::kZoomIn; - break; - case ui::CursorType::kZoomOut: - auraType = ui::CursorType::kZoomOut; - break; -#else - case ui::CursorType::kVerticalText: - case ui::CursorType::kCell: - case ui::CursorType::kContextMenu: - case ui::CursorType::kZoomIn: - case ui::CursorType::kZoomOut: - // FIXME: Support on OS X + case ui::mojom::CursorType::kVerticalText: + case ui::mojom::CursorType::kCell: + case ui::mojom::CursorType::kContextMenu: + case ui::mojom::CursorType::kZoomIn: + case ui::mojom::CursorType::kZoomOut: + if (updateCursorFromResource(cursorInfo.type())) + return; break; -#endif - case ui::CursorType::kNoDrop: - case ui::CursorType::kNotAllowed: + case ui::mojom::CursorType::kNoDrop: + case ui::mojom::CursorType::kNotAllowed: shape = Qt::ForbiddenCursor; break; - case ui::CursorType::kNone: + case ui::mojom::CursorType::kNone: shape = Qt::BlankCursor; break; - case ui::CursorType::kGrab: + case ui::mojom::CursorType::kGrab: shape = Qt::OpenHandCursor; break; - case ui::CursorType::kGrabbing: + case ui::mojom::CursorType::kGrabbing: shape = Qt::ClosedHandCursor; break; - case ui::CursorType::kCustom: - if (cursorInfo.custom_image.colorType() == SkColorType::kN32_SkColorType) { - QImage cursor = toQImage(cursorInfo.custom_image, QImage::Format_ARGB32); - m_delegate->updateCursor(QCursor(QPixmap::fromImage(cursor), cursorInfo.hotspot.x(), cursorInfo.hotspot.y())); + case ui::mojom::CursorType::kCustom: + if (cursorInfo.custom_bitmap().colorType() == SkColorType::kN32_SkColorType) { + QImage cursor = toQImage(cursorInfo.custom_bitmap(), QImage::Format_ARGB32); + m_delegate->updateCursor(QCursor(QPixmap::fromImage(cursor), cursorInfo.custom_hotspot().x(), cursorInfo.custom_hotspot().y())); return; } break; } -#if defined(USE_AURA) - if (auraType != ui::CursorType::kNull) { - int resourceId; - gfx::Point hotspot; - // GetCursorDataFor only knows hotspots for 1x and 2x cursor images, in physical pixels. - qreal hotspotDpr = m_screenInfo.device_scale_factor <= 1.0f ? 1.0f : 2.0f; - if (ui::GetCursorDataFor(ui::CursorSize::kNormal, auraType, hotspotDpr, &resourceId, &hotspot)) { - if (const gfx::ImageSkia *imageSkia = ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resourceId)) { - QImage imageQt = toQImage(imageSkia->GetRepresentation(m_screenInfo.device_scale_factor)); - - // Convert hotspot coordinates into device-independent pixels. - qreal hotX = hotspot.x() / hotspotDpr; - qreal hotY = hotspot.y() / hotspotDpr; - -#if defined(Q_OS_LINUX) - // QTBUG-68571: On Linux (xcb, wayland, eglfs), hotspot coordinates must be in physical pixels. - qreal imageDpr = imageQt.devicePixelRatio(); - hotX *= imageDpr; - hotY *= imageDpr; -#endif - - m_delegate->updateCursor(QCursor(QPixmap::fromImage(std::move(imageQt)), qRound(hotX), qRound(hotY))); - return; - } - } - } -#endif m_delegate->updateCursor(QCursor(shape)); } +content::CursorManager *RenderWidgetHostViewQt::GetCursorManager() +{ + return m_cursorManager.get(); +} + void RenderWidgetHostViewQt::SetIsLoading(bool) { // We use WebContentsDelegateQt::LoadingStateChanged to notify about loading state. @@ -707,6 +815,18 @@ void RenderWidgetHostViewQt::RenderProcessGone() Destroy(); } +bool RenderWidgetHostViewQt::TransformPointToCoordSpaceForView(const gfx::PointF &point, + content::RenderWidgetHostViewBase *target_view, + gfx::PointF *transformed_point) +{ + if (target_view == this) { + *transformed_point = point; + return true; + } + + return target_view->TransformPointToLocalCoordSpace(point, GetCurrentSurfaceId(), transformed_point); +} + void RenderWidgetHostViewQt::Destroy() { delete this; @@ -719,31 +839,11 @@ void RenderWidgetHostViewQt::SetTooltipText(const base::string16 &tooltip_text) void RenderWidgetHostViewQt::DisplayTooltipText(const base::string16 &tooltip_text) { - if (m_adapterClient) + if (host()->delegate() && m_adapterClient) m_adapterClient->setToolTip(toQt(tooltip_text)); } -void RenderWidgetHostViewQt::DidCreateNewRendererCompositorFrameSink(viz::mojom::CompositorFrameSinkClient *frameSinkClient) -{ - DCHECK(!m_enableViz); - m_compositor->setFrameSinkClient(frameSinkClient); -} - -void RenderWidgetHostViewQt::SubmitCompositorFrame(const viz::LocalSurfaceId &local_surface_id, viz::CompositorFrame frame, base::Optional<viz::HitTestRegionList> hit_test_region_list) -{ - DCHECK(!m_enableViz); - - // Force to process swap messages - uint32_t frame_token = frame.metadata.frame_token; - if (frame_token) - OnFrameTokenChangedForView(frame_token); - - m_compositor->submitFrame( - std::move(frame), - base::BindOnce(&RenderWidgetHostViewQt::callUpdate, base::Unretained(this))); -} - -void RenderWidgetHostViewQt::GetScreenInfo(content::ScreenInfo *results) +void RenderWidgetHostViewQt::GetScreenInfo(blink::ScreenInfo *results) { *results = m_screenInfo; } @@ -753,20 +853,16 @@ gfx::Rect RenderWidgetHostViewQt::GetBoundsInRootWindow() return m_windowRectInDips; } -void RenderWidgetHostViewQt::ClearCompositorFrame() -{ -} - void RenderWidgetHostViewQt::OnUpdateTextInputStateCalled(content::TextInputManager *text_input_manager, RenderWidgetHostViewBase *updated_view, bool did_update_state) { Q_UNUSED(text_input_manager); Q_UNUSED(updated_view); Q_UNUSED(did_update_state); - const content::TextInputState *state = text_input_manager_->GetTextInputState(); + const ui::mojom::TextInputState *state = text_input_manager_->GetTextInputState(); if (!state) { - m_delegate->inputMethodStateChanged(false /*editorVisible*/, false /*passwordInput*/); - m_delegate->setInputMethodHints(Qt::ImhNone); + // Do not reset input method state here because an editable node might be still focused and + // this would hide the virtual keyboard if a child of the focused node is removed. return; } @@ -778,14 +874,14 @@ void RenderWidgetHostViewQt::OnUpdateTextInputStateCalled(content::TextInputMana #endif m_surroundingText = toQt(state->value); // Remove IME composition text from the surrounding text - if (state->composition_start != -1 && state->composition_end != -1) - m_surroundingText.remove(state->composition_start, state->composition_end - state->composition_start); + if (state->composition.has_value()) + m_surroundingText.remove(state->composition->start(), state->composition->end() - state->composition->start()); // In case of text selection, the update is expected in RenderWidgetHostViewQt::selectionChanged(). if (GetSelectedText().empty()) { // At this point it is unknown whether the text input state has been updated due to a text selection. // Keep the cursor position updated for cursor movements too. - m_cursorPosition = state->selection_start; + m_cursorPosition = state->selection.start(); m_delegate->inputMethodStateChanged(type != ui::TEXT_INPUT_TYPE_NONE, type == ui::TEXT_INPUT_TYPE_PASSWORD); } @@ -795,7 +891,7 @@ void RenderWidgetHostViewQt::OnUpdateTextInputStateCalled(content::TextInputMana } // Ignore selection change triggered by ime composition unless it clears an actual text selection - if (state->composition_start != -1 && m_emptyPreviousSelection) { + if (state->composition.has_value() && m_emptyPreviousSelection) { m_imState = 0; return; } @@ -829,7 +925,7 @@ void RenderWidgetHostViewQt::OnTextSelectionChanged(content::TextInputManager *t #if defined(USE_OZONE) if (!selection->selected_text().empty() && selection->user_initiated()) { // Set the CLIPBOARD_TYPE_SELECTION to the ui::Clipboard. - ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardType::kSelection); + ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardBuffer::kSelection); clipboard_writer.WriteText(selection->selected_text()); } #endif // defined(USE_OZONE) @@ -867,7 +963,7 @@ void RenderWidgetHostViewQt::selectionChanged() // RenderWidgetHostViewQt::OnUpdateTextInputStateCalled() does not update the cursor position // if the selection is cleared because TextInputState changes before the TextSelection change. Q_ASSERT(text_input_manager_->GetTextInputState()); - m_cursorPosition = text_input_manager_->GetTextInputState()->selection_start; + m_cursorPosition = text_input_manager_->GetTextInputState()->selection.start(); m_delegate->inputMethodStateChanged(true /*editorVisible*/, type == ui::TEXT_INPUT_TYPE_PASSWORD); m_anchorPositionWithinSelection = m_cursorPosition; @@ -926,16 +1022,16 @@ void RenderWidgetHostViewQt::OnGestureEvent(const ui::GestureEventData& gesture) if (m_touchSelectionController && m_touchSelectionControllerClient) { switch (event.GetType()) { - case blink::WebInputEvent::kGestureLongPress: + case blink::WebInputEvent::Type::kGestureLongPress: m_touchSelectionController->HandleLongPressEvent(event.TimeStamp(), event.PositionInWidget()); break; - case blink::WebInputEvent::kGestureTap: + case blink::WebInputEvent::Type::kGestureTap: m_touchSelectionController->HandleTapEvent(event.PositionInWidget(), event.data.tap.tap_count); break; - case blink::WebInputEvent::kGestureScrollBegin: + case blink::WebInputEvent::Type::kGestureScrollBegin: m_touchSelectionControllerClient->onScrollBegin(); break; - case blink::WebInputEvent::kGestureScrollEnd: + case blink::WebInputEvent::Type::kGestureScrollEnd: m_touchSelectionControllerClient->onScrollEnd(); break; default: @@ -943,7 +1039,8 @@ void RenderWidgetHostViewQt::OnGestureEvent(const ui::GestureEventData& gesture) } } - host()->ForwardGestureEvent(event); + if (host()->delegate() && host()->delegate()->GetInputEventRouter()) + host()->delegate()->GetInputEventRouter()->RouteGestureEvent(this, &event, ui::LatencyInfo()); } void RenderWidgetHostViewQt::DidStopFlinging() @@ -961,7 +1058,7 @@ viz::ScopedSurfaceIdAllocator RenderWidgetHostViewQt::DidUpdateVisualProperties( void RenderWidgetHostViewQt::OnDidUpdateVisualPropertiesComplete(const cc::RenderFrameMetadata &metadata) { - synchronizeVisualProperties(metadata.local_surface_id_allocation); + synchronizeVisualProperties(metadata.local_surface_id); } void RenderWidgetHostViewQt::OnDidFirstVisuallyNonEmptyPaint() @@ -976,7 +1073,6 @@ void RenderWidgetHostViewQt::OnDidFirstVisuallyNonEmptyPaint() void RenderWidgetHostViewQt::scheduleUpdate() { - DCHECK(m_enableViz); m_taskRunner->PostTask( FROM_HERE, base::BindOnce(&RenderWidgetHostViewQt::callUpdate, m_weakPtrFactory.GetWeakPtr())); @@ -996,44 +1092,34 @@ void RenderWidgetHostViewQt::callUpdate() QSGNode *RenderWidgetHostViewQt::updatePaintNode(QSGNode *oldNode) { - if (m_enableViz) - return m_displayFrameSink->updatePaintNode(oldNode, m_delegate.get()); - return m_compositor->updatePaintNode(oldNode, m_delegate.get()); + return m_displayFrameSink->updatePaintNode(oldNode, m_delegate.get()); } void RenderWidgetHostViewQt::notifyShown() { - if (m_enableViz) { - // Handle possible frame eviction: - if (!m_dfhLocalSurfaceIdAllocator.HasValidLocalSurfaceIdAllocation()) - m_dfhLocalSurfaceIdAllocator.GenerateId(); - if (m_visible) - return; - m_visible = true; - } + // Handle possible frame eviction: + if (!m_dfhLocalSurfaceIdAllocator.HasValidLocalSurfaceId()) + m_dfhLocalSurfaceIdAllocator.GenerateId(); + if (m_visible) + return; + m_visible = true; - host()->WasShown(base::nullopt); + host()->WasShown(nullptr); - if (m_enableViz) { - m_delegatedFrameHost->AttachToCompositor(m_uiCompositor.get()); - m_delegatedFrameHost->WasShown(GetLocalSurfaceIdAllocation().local_surface_id(), - m_viewRectInDips.size(), - base::nullopt); - } + m_delegatedFrameHost->AttachToCompositor(m_uiCompositor.get()); + m_delegatedFrameHost->WasShown(GetLocalSurfaceId(), + m_viewRectInDips.size(), + nullptr); } void RenderWidgetHostViewQt::notifyHidden() { - if (m_enableViz) { - if (!m_visible) - return; - m_visible = false; - host()->WasHidden(); - m_delegatedFrameHost->WasHidden(content::DelegatedFrameHost::HiddenCause::kOther); - m_delegatedFrameHost->DetachFromCompositor(); - } else { - host()->WasHidden(); - } + if (!m_visible) + return; + m_visible = false; + host()->WasHidden(); + m_delegatedFrameHost->WasHidden(content::DelegatedFrameHost::HiddenCause::kOther); + m_delegatedFrameHost->DetachFromCompositor(); } void RenderWidgetHostViewQt::visualPropertiesChanged() @@ -1048,7 +1134,7 @@ void RenderWidgetHostViewQt::visualPropertiesChanged() m_windowRectInDips = toGfx(m_delegate->windowGeometry()); QWindow *window = m_delegate->window(); - content::ScreenInfo oldScreenInfo = m_screenInfo; + blink::ScreenInfo oldScreenInfo = m_screenInfo; m_screenInfo = screenInfoFromQScreen(window ? window->screen() : nullptr); if (m_viewRectInDips != oldViewRect || m_windowRectInDips != oldWindowRect) @@ -1089,7 +1175,7 @@ bool RenderWidgetHostViewQt::forwardEvent(QEvent *event) #endif }; - if (!inputMethodQuery(Qt::ImEnabled).toBool() && !acceptKeyOutOfInputField(keyEvent)) + if (!inputMethodQuery(Qt::ImEnabled).toBool() && !(inputMethodQuery(Qt::ImHints).toInt() & Qt::ImhHiddenText) && !acceptKeyOutOfInputField(keyEvent)) return false; Q_ASSERT(m_editCommand.empty()); @@ -1158,9 +1244,17 @@ bool RenderWidgetHostViewQt::forwardEvent(QEvent *event) case QEvent::InputMethodQuery: handleInputMethodQueryEvent(static_cast<QInputMethodQueryEvent*>(event)); break; - case QEvent::HoverLeave: case QEvent::Leave: - host()->ForwardMouseEvent(WebEventFactory::toWebMouseEvent(event)); +#ifdef Q_OS_WIN + if (m_mouseButtonPressed > 0) + return false; +#endif + case QEvent::HoverLeave: { + if (host()->delegate() && host()->delegate()->GetInputEventRouter()) { + auto webEvent = WebEventFactory::toWebMouseEvent(event); + host()->delegate()->GetInputEventRouter()->RouteMouseEvent(this, &webEvent, ui::LatencyInfo()); + } + } break; default: return false; @@ -1228,10 +1322,12 @@ void RenderWidgetHostViewQt::closePopup() host()->LostFocus(); } -void RenderWidgetHostViewQt::ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch, content::InputEventAckState ack_result) { +void RenderWidgetHostViewQt::ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch, blink::mojom::InputEventResultState ack_result) +{ Q_UNUSED(touch); - const bool eventConsumed = ack_result == content::INPUT_EVENT_ACK_STATE_CONSUMED; - m_gestureProvider.OnTouchEventAck(touch.event.unique_touch_event_id, eventConsumed, /*fixme: ?? */false); + const bool eventConsumed = ack_result == blink::mojom::InputEventResultState::kConsumed; + const bool isSetNonBlocking = content::InputEventResultStateIsSetNonBlocking(ack_result); + m_gestureProvider.OnTouchEventAck(touch.event.unique_touch_event_id, eventConsumed, isSetNonBlocking); } void RenderWidgetHostViewQt::processMotionEvent(const ui::MotionEvent &motionEvent) @@ -1239,30 +1335,35 @@ void RenderWidgetHostViewQt::processMotionEvent(const ui::MotionEvent &motionEve auto result = m_gestureProvider.OnTouchEvent(motionEvent); if (!result.succeeded) return; - blink::WebTouchEvent touchEvent = ui::CreateWebTouchEventFromMotionEvent(motionEvent, result.moved_beyond_slop_region, false /*hovering, FIXME ?*/); - host()->ForwardTouchEventWithLatencyInfo(touchEvent, CreateLatencyInfo(touchEvent)); + if (host()->delegate() && host()->delegate()->GetInputEventRouter()) + host()->delegate()->GetInputEventRouter()->RouteTouchEvent(this, &touchEvent, CreateLatencyInfo(touchEvent)); } -QList<QTouchEvent::TouchPoint> RenderWidgetHostViewQt::mapTouchPointIds(const QList<QTouchEvent::TouchPoint> &inputPoints) +QList<RenderWidgetHostViewQt::TouchPoint> RenderWidgetHostViewQt::mapTouchPoints(const QList<QTouchEvent::TouchPoint> &input) { - QList<QTouchEvent::TouchPoint> outputPoints = inputPoints; - for (int i = 0; i < outputPoints.size(); ++i) { - QTouchEvent::TouchPoint &point = outputPoints[i]; + QList<TouchPoint> output; + for (int i = 0; i < input.size(); ++i) { + const QTouchEvent::TouchPoint &point = input[i]; int qtId = point.id(); QMap<int, int>::const_iterator it = m_touchIdMapping.find(qtId); if (it == m_touchIdMapping.end()) it = m_touchIdMapping.insert(qtId, firstAvailableId(m_touchIdMapping)); - point.setId(it.value()); - if (point.state() == Qt::TouchPointReleased) - m_touchIdMapping.remove(qtId); + output.append(qMakePair(it.value(), point)); } - return outputPoints; + Q_ASSERT(output.size() == std::accumulate(output.cbegin(), output.cend(), QSet<int>(), + [] (QSet<int> s, const TouchPoint &p) { s.insert(p.second.id()); return s; }).size()); + + for (auto &&point : qAsConst(input)) + if (point.state() == Qt::TouchPointReleased) + m_touchIdMapping.remove(point.id()); + + return output; } bool RenderWidgetHostViewQt::IsPopup() const @@ -1272,12 +1373,11 @@ bool RenderWidgetHostViewQt::IsPopup() const void RenderWidgetHostViewQt::handleMouseEvent(QMouseEvent* event) { - // Don't forward mouse events synthesized by the system, which are caused by genuine touch - // events. Chromium would then process for e.g. a mouse click handler twice, once due to the - // system synthesized mouse event, and another time due to a touch-to-gesture-to-mouse - // transformation done by Chromium. - if (event->source() == Qt::MouseEventSynthesizedBySystem) - return; + if (event->type() == QEvent::MouseButtonPress) + m_mouseButtonPressed++; + if (event->type() == QEvent::MouseButtonRelease) + m_mouseButtonPressed--; + handlePointerEvent<QMouseEvent>(event); } @@ -1315,27 +1415,27 @@ void RenderWidgetHostViewQt::handleKeyEvent(QKeyEvent *ev) return; content::NativeWebKeyboardEvent webEvent = WebEventFactory::toWebKeyboardEvent(ev); - if (webEvent.GetType() == blink::WebInputEvent::kRawKeyDown && !m_editCommand.empty()) { + if (webEvent.GetType() == blink::WebInputEvent::Type::kRawKeyDown && !m_editCommand.empty()) { ui::LatencyInfo latency; latency.set_source_event_type(ui::SourceEventType::KEY_PRESS); - content::EditCommands commands; - commands.emplace_back(m_editCommand, ""); + std::vector<blink::mojom::EditCommandPtr> commands; + commands.emplace_back(blink::mojom::EditCommand::New(m_editCommand, "")); m_editCommand.clear(); - host()->ForwardKeyboardEventWithCommands(webEvent, latency, &commands, nullptr); + GetFocusedWidget()->ForwardKeyboardEventWithCommands(webEvent, latency, std::move(commands), nullptr); return; } - bool keyDownTextInsertion = webEvent.GetType() == blink::WebInputEvent::kRawKeyDown && webEvent.text[0]; + bool keyDownTextInsertion = webEvent.GetType() == blink::WebInputEvent::Type::kRawKeyDown && webEvent.text[0]; webEvent.skip_in_browser = keyDownTextInsertion; - host()->ForwardKeyboardEvent(webEvent); + GetFocusedWidget()->ForwardKeyboardEvent(webEvent); if (keyDownTextInsertion) { // Blink won't consume the RawKeyDown, but rather the Char event in this case. // The RawKeyDown is skipped on the way back (see above). // The same os_event will be set on both NativeWebKeyboardEvents. webEvent.skip_in_browser = false; - webEvent.SetType(blink::WebInputEvent::kChar); - host()->ForwardKeyboardEvent(webEvent); + webEvent.SetType(blink::WebInputEvent::Type::kChar); + GetFocusedWidget()->ForwardKeyboardEvent(webEvent); } } @@ -1373,7 +1473,9 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev) end = qMax(0, start + end); } - underlines.push_back(ui::ImeTextSpan(ui::ImeTextSpan::Type::kComposition, start, end, ui::ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT)); + underlines.push_back(ui::ImeTextSpan(ui::ImeTextSpan::Type::kComposition, start, end, + ui::ImeTextSpan::Thickness::kThin, ui::ImeTextSpan::UnderlineStyle::kSolid, + SK_ColorTRANSPARENT)); QTextCharFormat format = qvariant_cast<QTextFormat>(attribute.value).toCharFormat(); if (format.underlineStyle() != QTextCharFormat::NoUnderline) @@ -1417,9 +1519,8 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev) } if (hasSelection) { - content::mojom::FrameInputHandler *frameInputHandler = getFrameInputHandler(); - if (frameInputHandler) - frameInputHandler->SetEditableSelectionOffsets(selectionRange.start(), selectionRange.end()); + if (auto *frameWidgetInputHandler = getFrameWidgetInputHandler()) + frameWidgetInputHandler->SetEditableSelectionOffsets(selectionRange.start(), selectionRange.end()); } int replacementLength = ev->replacementLength(); @@ -1502,8 +1603,9 @@ void RenderWidgetHostViewQt::handleWheelEvent(QWheelEvent *ev) Q_ASSERT(m_pendingWheelEvents.isEmpty()); blink::WebMouseWheelEvent webEvent = WebEventFactory::toWebWheelEvent(ev); m_wheelAckPending = (webEvent.phase != blink::WebMouseWheelEvent::kPhaseEnded); - m_mouseWheelPhaseHandler.AddPhaseIfNeededAndScheduleEndEvent(webEvent, false); - host()->ForwardWheelEvent(webEvent); + m_mouseWheelPhaseHandler.AddPhaseIfNeededAndScheduleEndEvent(webEvent, true); + if (host()->delegate() && host()->delegate()->GetInputEventRouter()) + host()->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(this, &webEvent, ui::LatencyInfo()); return; } if (!m_pendingWheelEvents.isEmpty()) { @@ -1514,7 +1616,7 @@ void RenderWidgetHostViewQt::handleWheelEvent(QWheelEvent *ev) m_pendingWheelEvents.append(WebEventFactory::toWebWheelEvent(ev)); } -void RenderWidgetHostViewQt::WheelEventAck(const blink::WebMouseWheelEvent &event, content::InputEventAckState /*ack_result*/) +void RenderWidgetHostViewQt::WheelEventAck(const blink::WebMouseWheelEvent &event, blink::mojom::InputEventResultState /*ack_result*/) { if (event.phase == blink::WebMouseWheelEvent::kPhaseEnded) return; @@ -1523,21 +1625,30 @@ void RenderWidgetHostViewQt::WheelEventAck(const blink::WebMouseWheelEvent &even while (!m_pendingWheelEvents.isEmpty() && !m_wheelAckPending) { blink::WebMouseWheelEvent webEvent = m_pendingWheelEvents.takeFirst(); m_wheelAckPending = (webEvent.phase != blink::WebMouseWheelEvent::kPhaseEnded); - m_mouseWheelPhaseHandler.AddPhaseIfNeededAndScheduleEndEvent(webEvent, false); - host()->ForwardWheelEvent(webEvent); + m_mouseWheelPhaseHandler.AddPhaseIfNeededAndScheduleEndEvent(webEvent, true); + if (host()->delegate() && host()->delegate()->GetInputEventRouter()) + host()->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(this, &webEvent, ui::LatencyInfo()); } - // TODO: We could forward unhandled wheelevents to our parent. } -content::MouseWheelPhaseHandler *RenderWidgetHostViewQt::GetMouseWheelPhaseHandler() +void RenderWidgetHostViewQt::GestureEventAck(const blink::WebGestureEvent &event, blink::mojom::InputEventResultState ack_result) { - return &m_mouseWheelPhaseHandler; + // Forward unhandled scroll events back as wheel events + if (event.GetType() != blink::WebInputEvent::Type::kGestureScrollUpdate) + return; + switch (ack_result) { + case blink::mojom::InputEventResultState::kNotConsumed: + case blink::mojom::InputEventResultState::kNoConsumerExists: + WebEventFactory::sendUnhandledWheelEvent(event, delegate()); + break; + default: + break; + } } -void RenderWidgetHostViewQt::clearPreviousTouchMotionState() +content::MouseWheelPhaseHandler *RenderWidgetHostViewQt::GetMouseWheelPhaseHandler() { - m_previousTouchPoints.clear(); - m_touchMotionStarted = false; + return &m_mouseWheelPhaseHandler; } #ifndef QT_NO_GESTURES @@ -1545,8 +1656,12 @@ void RenderWidgetHostViewQt::handleGestureEvent(QNativeGestureEvent *ev) { const Qt::NativeGestureType type = ev->gestureType(); // These are the only supported gestures by Chromium so far. - if (type == Qt::ZoomNativeGesture || type == Qt::SmartZoomNativeGesture) { - host()->ForwardGestureEvent(WebEventFactory::toWebGestureEvent(ev)); + if (type == Qt::ZoomNativeGesture || type == Qt::SmartZoomNativeGesture + || type == Qt::BeginNativeGesture || type == Qt::EndNativeGesture) { + if (host()->delegate() && host()->delegate()->GetInputEventRouter()) { + auto webEvent = WebEventFactory::toWebGestureEvent(ev); + host()->delegate()->GetInputEventRouter()->RouteGestureEvent(this, &webEvent, ui::LatencyInfo()); + } } } #endif @@ -1574,10 +1689,34 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev) m_eventsToNowDelta = base::TimeTicks::Now() - eventTimestamp; eventTimestamp += m_eventsToNowDelta; - QList<QTouchEvent::TouchPoint> touchPoints = mapTouchPointIds(ev->touchPoints()); - { - ui::MotionEvent::Action action; - switch (touchPoints[0].state()) { + auto touchPoints = mapTouchPoints(ev->touchPoints()); + // Make sure that POINTER_DOWN action is delivered before MOVE, and MOVE before POINTER_UP + std::sort(touchPoints.begin(), touchPoints.end(), [] (const TouchPoint &l, const TouchPoint &r) { + return l.second.state() < r.second.state(); + }); + + auto sc = qScopeGuard([&] () { + switch (ev->type()) { + case QEvent::TouchCancel: + for (auto &&it : qAsConst(touchPoints)) + m_touchIdMapping.remove(it.second.id()); + Q_FALLTHROUGH(); + + case QEvent::TouchEnd: + m_previousTouchPoints.clear(); + m_touchMotionStarted = false; + break; + + default: + m_previousTouchPoints = touchPoints; + break; + } + }); + + ui::MotionEvent::Action action; + // Check first if the touch event should be routed to the selectionController + if (!touchPoints.isEmpty()) { + switch (touchPoints[0].second.state()) { case Qt::TouchPointPressed: action = ui::MotionEvent::Action::DOWN; break; @@ -1591,14 +1730,24 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev) action = ui::MotionEvent::Action::NONE; break; } - - MotionEventQt motionEvent(touchPoints, eventTimestamp, action, ev->modifiers(), 0); - if (m_touchSelectionController->WillHandleTouchEvent(motionEvent)) { - ev->accept(); + } else { + // An empty touchPoints always corresponds to a TouchCancel event. + // We can't forward touch cancellations without a previously processed touch event, + // as Chromium expects the previous touchPoints for Action::CANCEL. + // If both are empty that means the TouchCancel was sent without an ongoing touch, + // so there's nothing to cancel anyway. + Q_ASSERT(ev->type() == QEvent::TouchCancel); + touchPoints = m_previousTouchPoints; + if (touchPoints.isEmpty()) return; - } + + action = ui::MotionEvent::Action::CANCEL; } + MotionEventQt me(touchPoints, eventTimestamp, action, ev->modifiers()); + if (m_touchSelectionController->WillHandleTouchEvent(me)) + return; + switch (ev->type()) { case QEvent::TouchBegin: m_sendMotionActionDown = true; @@ -1610,25 +1759,15 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev) break; case QEvent::TouchCancel: { - // Don't process a TouchCancel event if no motion was started beforehand, or if there are - // no touch points in the current event or in the previously processed event. - if (!m_touchMotionStarted || (touchPoints.isEmpty() && m_previousTouchPoints.isEmpty())) { - clearPreviousTouchMotionState(); - return; + // Only process TouchCancel events received following a TouchBegin or TouchUpdate event + if (m_touchMotionStarted) { + MotionEventQt cancelEvent(touchPoints, eventTimestamp, ui::MotionEvent::Action::CANCEL, ev->modifiers()); + processMotionEvent(cancelEvent); } - // Use last saved touch points for the cancel event, to get rid of a QList assert, - // because Chromium expects a MotionEvent::ACTION_CANCEL instance to contain at least - // one touch point, whereas a QTouchCancel may not contain any touch points at all. - if (touchPoints.isEmpty()) - touchPoints = m_previousTouchPoints; - clearPreviousTouchMotionState(); - MotionEventQt cancelEvent(touchPoints, eventTimestamp, ui::MotionEvent::Action::CANCEL, ev->modifiers()); - processMotionEvent(cancelEvent); return; } case QEvent::TouchEnd: - clearPreviousTouchMotionState(); m_touchSelectionControllerClient->onTouchUp(); break; default: @@ -1648,36 +1787,49 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev) #endif } - // Make sure that ACTION_POINTER_DOWN is delivered before ACTION_MOVE, - // and ACTION_MOVE before ACTION_POINTER_UP. - std::sort(touchPoints.begin(), touchPoints.end(), compareTouchPoints); + // MEMO for the basis of this logic look into: + // * blink_event_util.cc:ToWebTouchPointState: which is used later to forward touch event + // composed from motion event after gesture recognition + // * gesture_detector.cc:GestureDetector::OnTouchEvent: contains logic for every motion + // event action and corresponding gesture recognition routines + // * input_router_imp.cc:InputRouterImp::SetMovementXYForTouchPoints: expectation about + // touch event content like number of points for different states - m_previousTouchPoints = touchPoints; - for (int i = 0; i < touchPoints.size(); ++i) { - ui::MotionEvent::Action action; - switch (touchPoints[i].state()) { - case Qt::TouchPointPressed: - if (m_sendMotionActionDown) { - action = ui::MotionEvent::Action::DOWN; - m_sendMotionActionDown = false; - } else { - action = ui::MotionEvent::Action::POINTER_DOWN; + int lastPressIndex = -1; + while ((lastPressIndex + 1) < touchPoints.size() && touchPoints[lastPressIndex + 1].second.state() == Qt::TouchPointPressed) + ++lastPressIndex; + + switch (ev->type()) { + case QEvent::TouchBegin: + processMotionEvent(MotionEventQt(touchPoints.mid(lastPressIndex), + eventTimestamp, ui::MotionEvent::Action::DOWN, ev->modifiers())); + --lastPressIndex; + Q_FALLTHROUGH(); + + case QEvent::TouchUpdate: + for (; lastPressIndex >= 0; --lastPressIndex) { + Q_ASSERT(touchPoints[lastPressIndex].second.state() == Qt::TouchPointPressed); + MotionEventQt me(touchPoints.mid(lastPressIndex), eventTimestamp, ui::MotionEvent::Action::POINTER_DOWN, ev->modifiers(), 0); + processMotionEvent(me); + } + + if (ev->touchPointStates() & Qt::TouchPointMoved) + processMotionEvent(MotionEventQt(touchPoints, eventTimestamp, ui::MotionEvent::Action::MOVE, ev->modifiers())); + + Q_FALLTHROUGH(); + + case QEvent::TouchEnd: + while (!touchPoints.isEmpty() && touchPoints.back().second.state() == Qt::TouchPointReleased) { + auto action = touchPoints.size() > 1 ? ui::MotionEvent::Action::POINTER_UP : ui::MotionEvent::Action::UP; + int index = action == ui::MotionEvent::Action::POINTER_UP ? touchPoints.size() - 1 : -1; + processMotionEvent(MotionEventQt(touchPoints, eventTimestamp, action, ev->modifiers(), index)); + touchPoints.pop_back(); } break; - case Qt::TouchPointMoved: - action = ui::MotionEvent::Action::MOVE; - break; - case Qt::TouchPointReleased: - action = touchPoints.size() > 1 ? ui::MotionEvent::Action::POINTER_UP : - ui::MotionEvent::Action::UP; - break; - default: - // Ignore Qt::TouchPointStationary - continue; - } - MotionEventQt motionEvent(touchPoints, eventTimestamp, action, ev->modifiers(), i); - processMotionEvent(motionEvent); + default: + Q_ASSERT_X(false, __FUNCTION__, "Other event types are expected to be already handled."); + break; } } @@ -1694,13 +1846,14 @@ void RenderWidgetHostViewQt::handlePointerEvent(T *event) // Currently WebMouseEvent is a subclass of WebPointerProperties, so basically // tablet events are mouse events with extra properties. blink::WebMouseEvent webEvent = WebEventFactory::toWebMouseEvent(event); - if ((webEvent.GetType() == blink::WebInputEvent::kMouseDown || webEvent.GetType() == blink::WebInputEvent::kMouseUp) + if ((webEvent.GetType() == blink::WebInputEvent::Type::kMouseDown || webEvent.GetType() == blink::WebInputEvent::Type::kMouseUp) && webEvent.button == blink::WebMouseEvent::Button::kNoButton) { - // Blink can only handle the 3 main mouse-buttons and may assert when processing mouse-down for no button. + // Blink can only handle the 5 main mouse-buttons and may assert when processing mouse-down for no button. + LOG(INFO) << "Unhandled mouse button"; return; } - if (webEvent.GetType() == blink::WebInputEvent::kMouseDown) { + if (webEvent.GetType() == blink::WebInputEvent::Type::kMouseDown) { if (event->button() != m_clickHelper.lastPressButton || (event->timestamp() - m_clickHelper.lastPressTimestamp > static_cast<ulong>(qGuiApp->styleHints()->mouseDoubleClickInterval())) || (event->pos() - m_clickHelper.lastPressPosition).manhattanLength() > qGuiApp->styleHints()->startDragDistance() @@ -1713,6 +1866,9 @@ void RenderWidgetHostViewQt::handlePointerEvent(T *event) m_clickHelper.lastPressPosition = QPointF(event->pos()).toPoint(); } + if (webEvent.GetType() == blink::WebInputEvent::Type::kMouseUp) + webEvent.click_count = m_clickHelper.clickCounter; + webEvent.movement_x = event->globalX() - m_previousMousePosition.x(); webEvent.movement_y = event->globalY() - m_previousMousePosition.y(); @@ -1721,7 +1877,7 @@ void RenderWidgetHostViewQt::handlePointerEvent(T *event) else m_previousMousePosition = event->globalPos(); - if (m_imeInProgress && webEvent.GetType() == blink::WebInputEvent::kMouseDown) { + if (m_imeInProgress && webEvent.GetType() == blink::WebInputEvent::Type::kMouseDown) { m_imeInProgress = false; // Tell input method to commit the pre-edit string entered so far, and finish the // composition operation. @@ -1734,12 +1890,16 @@ void RenderWidgetHostViewQt::handlePointerEvent(T *event) #endif } - host()->ForwardMouseEvent(webEvent); + if (host()->delegate() && host()->delegate()->GetInputEventRouter()) + host()->delegate()->GetInputEventRouter()->RouteMouseEvent(this, &webEvent, ui::LatencyInfo()); } void RenderWidgetHostViewQt::handleHoverEvent(QHoverEvent *ev) { - host()->ForwardMouseEvent(WebEventFactory::toWebMouseEvent(ev)); + if (host()->delegate() && host()->delegate()->GetInputEventRouter()) { + auto webEvent = WebEventFactory::toWebMouseEvent(ev); + host()->delegate()->GetInputEventRouter()->RouteMouseEvent(this, &webEvent, ui::LatencyInfo()); + } } void RenderWidgetHostViewQt::handleFocusEvent(QFocusEvent *ev) @@ -1754,6 +1914,8 @@ void RenderWidgetHostViewQt::handleFocusEvent(QFocusEvent *ev) else if (ev->reason() == Qt::BacktabFocusReason) viewHost->SetInitialFocus(true); ev->accept(); + + m_adapterClient->webContentsAdapter()->handlePendingMouseLockPermission(); } else if (ev->lostFocus()) { host()->SetActive(false); host()->LostFocus(); @@ -1761,32 +1923,13 @@ void RenderWidgetHostViewQt::handleFocusEvent(QFocusEvent *ev) } } -void RenderWidgetHostViewQt::SetNeedsBeginFrames(bool needs_begin_frames) -{ - m_needsBeginFrames = needs_begin_frames; - UpdateNeedsBeginFramesInternal(); -} - -content::RenderFrameHost *RenderWidgetHostViewQt::getFocusedFrameHost() -{ - content::RenderViewHostImpl *viewHost = content::RenderViewHostImpl::From(host()); - if (!viewHost) - return nullptr; - - content::FrameTreeNode *focusedFrame = viewHost->GetDelegate()->GetFrameTree()->GetFocusedFrame(); - if (!focusedFrame) - return nullptr; - - return focusedFrame->current_frame_host(); -} - -content::mojom::FrameInputHandler *RenderWidgetHostViewQt::getFrameInputHandler() +blink::mojom::FrameWidgetInputHandler *RenderWidgetHostViewQt::getFrameWidgetInputHandler() { - content::RenderFrameHostImpl *frameHost = static_cast<content::RenderFrameHostImpl *>(getFocusedFrameHost()); - if (!frameHost) + auto *focused_widget = GetFocusedWidget(); + if (!focused_widget) return nullptr; - return frameHost->GetFrameInputHandler(); + return focused_widget->GetFrameWidgetInputHandler(); } ui::TextInputType RenderWidgetHostViewQt::getTextInputType() const @@ -1797,43 +1940,44 @@ ui::TextInputType RenderWidgetHostViewQt::getTextInputType() const return ui::TEXT_INPUT_TYPE_NONE; } -void RenderWidgetHostViewQt::SetWantsAnimateOnlyBeginFrames() +viz::SurfaceId RenderWidgetHostViewQt::GetCurrentSurfaceId() const { - if (m_enableViz) - m_delegatedFrameHost->SetWantsAnimateOnlyBeginFrames(); + return m_delegatedFrameHost->GetCurrentSurfaceId(); } -viz::SurfaceId RenderWidgetHostViewQt::GetCurrentSurfaceId() const +const viz::FrameSinkId &RenderWidgetHostViewQt::GetFrameSinkId() const { - if (m_enableViz) - return m_delegatedFrameHost->GetCurrentSurfaceId(); - return viz::SurfaceId(); + return m_delegatedFrameHost->frame_sink_id(); } -const viz::FrameSinkId &RenderWidgetHostViewQt::GetFrameSinkId() const +const viz::LocalSurfaceId &RenderWidgetHostViewQt::GetLocalSurfaceId() const +{ + return m_dfhLocalSurfaceIdAllocator.GetCurrentLocalSurfaceId(); +} + +void RenderWidgetHostViewQt::FocusedNodeChanged(bool is_editable_node, const gfx::Rect& node_bounds_in_screen) { - if (m_enableViz) - return m_delegatedFrameHost->frame_sink_id(); - return m_frameSinkId; + Q_UNUSED(node_bounds_in_screen); + if (!is_editable_node) { + m_delegate->inputMethodStateChanged(false /*editorVisible*/, false /*passwordInput*/); + m_delegate->setInputMethodHints(Qt::ImhNone); + } } -const viz::LocalSurfaceIdAllocation &RenderWidgetHostViewQt::GetLocalSurfaceIdAllocation() const +base::flat_map<std::string, std::string> RenderWidgetHostViewQt::GetKeyboardLayoutMap() { - return m_dfhLocalSurfaceIdAllocator.GetCurrentLocalSurfaceIdAllocation(); + return ui::GenerateDomKeyboardLayoutMap(); } void RenderWidgetHostViewQt::TakeFallbackContentFrom(content::RenderWidgetHostView *view) { DCHECK(!static_cast<RenderWidgetHostViewBase*>(view)->IsRenderWidgetHostViewChildFrame()); - DCHECK(!static_cast<RenderWidgetHostViewBase*>(view)->IsRenderWidgetHostViewGuest()); RenderWidgetHostViewQt *viewQt = static_cast<RenderWidgetHostViewQt *>(view); base::Optional<SkColor> color = viewQt->GetBackgroundColor(); if (color) SetBackgroundColor(*color); - if (m_enableViz) { - m_delegatedFrameHost->TakeFallbackContentFrom(viewQt->m_delegatedFrameHost.get()); - host()->GetContentRenderingTimeoutFrom(viewQt->host()); - } + m_delegatedFrameHost->TakeFallbackContentFrom(viewQt->m_delegatedFrameHost.get()); + host()->GetContentRenderingTimeoutFrom(viewQt->host()); } void RenderWidgetHostViewQt::EnsureSurfaceSynchronizedForWebTest() @@ -1852,8 +1996,6 @@ void RenderWidgetHostViewQt::ResetFallbackToFirstNavigationSurface() void RenderWidgetHostViewQt::OnRenderFrameMetadataChangedAfterActivation() { - content::RenderWidgetHostViewBase::OnRenderFrameMetadataChangedAfterActivation(); - const cc::RenderFrameMetadata &metadata = host()->render_frame_metadata_provider()->LastRenderFrameMetadata(); if (metadata.selection.start != m_selectionStart || metadata.selection.end != m_selectionEnd) { m_selectionStart = metadata.selection.start; @@ -1865,33 +2007,31 @@ void RenderWidgetHostViewQt::OnRenderFrameMetadataChangedAfterActivation() gfx::SizeF contentsSize = metadata.root_layer_size; std::swap(m_lastScrollOffset, scrollOffset); std::swap(m_lastContentsSize, contentsSize); - if (scrollOffset != m_lastScrollOffset) + if (m_adapterClient && scrollOffset != m_lastScrollOffset) m_adapterClient->updateScrollPosition(toQt(m_lastScrollOffset)); - if (contentsSize != m_lastContentsSize) + if (m_adapterClient && contentsSize != m_lastContentsSize) m_adapterClient->updateContentsSize(toQt(m_lastContentsSize)); } -void RenderWidgetHostViewQt::synchronizeVisualProperties(const base::Optional<viz::LocalSurfaceIdAllocation> &childSurfaceId) +void RenderWidgetHostViewQt::synchronizeVisualProperties(const base::Optional<viz::LocalSurfaceId> &childSurfaceId) { if (childSurfaceId) m_dfhLocalSurfaceIdAllocator.UpdateFromChild(*childSurfaceId); else m_dfhLocalSurfaceIdAllocator.GenerateId(); - if (m_enableViz) { - gfx::Size viewSizeInDips = GetRequestedRendererSize(); - gfx::Size viewSizeInPixels = GetCompositorViewportPixelSize(); - m_rootLayer->SetBounds(gfx::Rect(gfx::Point(), viewSizeInPixels)); - m_uiCompositorLocalSurfaceIdAllocator.GenerateId(); - m_uiCompositor->SetScaleAndSize( - m_screenInfo.device_scale_factor, - viewSizeInPixels, - m_uiCompositorLocalSurfaceIdAllocator.GetCurrentLocalSurfaceIdAllocation()); - m_delegatedFrameHost->EmbedSurface( - m_dfhLocalSurfaceIdAllocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id(), - viewSizeInDips, - cc::DeadlinePolicy::UseDefaultDeadline()); - } + gfx::Size viewSizeInDips = GetRequestedRendererSize(); + gfx::Size viewSizeInPixels = GetCompositorViewportPixelSize(); + m_rootLayer->SetBounds(gfx::Rect(gfx::Point(), viewSizeInPixels)); + m_uiCompositorLocalSurfaceIdAllocator.GenerateId(); + m_uiCompositor->SetScaleAndSize( + m_screenInfo.device_scale_factor, + viewSizeInPixels, + m_uiCompositorLocalSurfaceIdAllocator.GetCurrentLocalSurfaceId()); + m_delegatedFrameHost->EmbedSurface( + m_dfhLocalSurfaceIdAllocator.GetCurrentLocalSurfaceId(), + viewSizeInDips, + cc::DeadlinePolicy::UseDefaultDeadline()); host()->SynchronizeVisualProperties(); } @@ -1901,12 +2041,9 @@ std::unique_ptr<content::SyntheticGestureTarget> RenderWidgetHostViewQt::CreateS return nullptr; } -void RenderWidgetHostViewQt::UpdateNeedsBeginFramesInternal() +ui::Compositor *RenderWidgetHostViewQt::GetCompositor() { - if (m_enableViz) - m_delegatedFrameHost->SetNeedsBeginFrames(m_needsBeginFrames); - else - m_compositor->setNeedsBeginFrames(m_needsBeginFrames); + return m_uiCompositor.get(); } } // namespace QtWebEngineCore diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h index 0e9d54b19..46c2547da 100644 --- a/src/core/render_widget_host_view_qt.h +++ b/src/core/render_widget_host_view_qt.h @@ -68,9 +68,6 @@ QT_END_NAMESPACE namespace content { class RenderFrameHost; class RenderWidgetHostImpl; -namespace mojom { -class FrameInputHandler; -} } namespace ui { @@ -79,7 +76,7 @@ class TouchSelectionController; namespace QtWebEngineCore { -class Compositor; +class GuestInputEventObserverQt; class TouchHandleDrawableClient; class TouchSelectionControllerClientQt; class TouchSelectionMenuController; @@ -106,6 +103,7 @@ class RenderWidgetHostViewQt , public RenderWidgetHostViewQtDelegateClient , public base::SupportsWeakPtr<RenderWidgetHostViewQt> , public content::TextInputManager::Observer + , public content::RenderFrameMetadataProvider::Observer , public DisplayConsumer { public: @@ -122,6 +120,7 @@ public: void setDelegate(RenderWidgetHostViewQtDelegate *delegate); WebContentsAdapterClient *adapterClient() { return m_adapterClient; } void setAdapterClient(WebContentsAdapterClient *adapterClient); + void setGuest(content::RenderWidgetHostImpl *); void InitAsChild(gfx::NativeView) override; void InitAsPopup(content::RenderWidgetHostView*, const gfx::Rect&) override; @@ -132,6 +131,8 @@ public: gfx::NativeViewAccessible GetNativeViewAccessible() override; void Focus() override; bool HasFocus() override; + bool IsMouseLocked() override; + viz::FrameSinkId GetRootFrameSinkId() override; bool IsSurfaceAvailableForCopy() override; void CopyFromSurface(const gfx::Rect &src_rect, const gfx::Size &output_size, @@ -141,39 +142,48 @@ public: bool IsShowing() override; gfx::Rect GetViewBounds() override; void UpdateBackgroundColor() override; - bool LockMouse() override; + blink::mojom::PointerLockResult LockMouse(bool) override; + blink::mojom::PointerLockResult ChangeMouseLock(bool) override; void UnlockMouse() override; void UpdateCursor(const content::WebCursor&) override; void DisplayCursor(const content::WebCursor&) override; + content::CursorManager *GetCursorManager() override; void SetIsLoading(bool) override; void ImeCancelComposition() override; void ImeCompositionRangeChanged(const gfx::Range&, const std::vector<gfx::Rect>&) override; void RenderProcessGone() override; + bool TransformPointToCoordSpaceForView(const gfx::PointF &point, + content::RenderWidgetHostViewBase *target_view, + gfx::PointF *transformed_point) override; void Destroy() override; void SetTooltipText(const base::string16 &tooltip_text) override; void DisplayTooltipText(const base::string16& tooltip_text) override; - void DidCreateNewRendererCompositorFrameSink(viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) override; - void SubmitCompositorFrame(const viz::LocalSurfaceId&, viz::CompositorFrame, base::Optional<viz::HitTestRegionList>) override; - void WheelEventAck(const blink::WebMouseWheelEvent &event, content::InputEventAckState ack_result) override; + void WheelEventAck(const blink::WebMouseWheelEvent &event, + blink::mojom::InputEventResultState ack_result) override; + void GestureEventAck(const blink::WebGestureEvent &event, + blink::mojom::InputEventResultState ack_result) override; content::MouseWheelPhaseHandler *GetMouseWheelPhaseHandler() override; viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties(const cc::RenderFrameMetadata &metadata) override; void OnDidUpdateVisualPropertiesComplete(const cc::RenderFrameMetadata &metadata); - void GetScreenInfo(content::ScreenInfo *results) override; + // Overridden from RenderWidgetHostViewBase: + void GetScreenInfo(blink::ScreenInfo *results) override; gfx::Rect GetBoundsInRootWindow() override; - void ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch, content::InputEventAckState ack_result) override; - void ClearCompositorFrame() override; - void SetNeedsBeginFrames(bool needs_begin_frames) override; - void SetWantsAnimateOnlyBeginFrames() override; + void ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch, + blink::mojom::InputEventResultState ack_result) override; viz::SurfaceId GetCurrentSurfaceId() const override; const viz::FrameSinkId &GetFrameSinkId() const override; - const viz::LocalSurfaceIdAllocation &GetLocalSurfaceIdAllocation() const override; + const viz::LocalSurfaceId &GetLocalSurfaceId() const override; + void FocusedNodeChanged(bool is_editable_node, const gfx::Rect& node_bounds_in_screen) override; + base::flat_map<std::string, std::string> GetKeyboardLayoutMap() override; + void TakeFallbackContentFrom(content::RenderWidgetHostView *view) override; void EnsureSurfaceSynchronizedForWebTest() override; uint32_t GetCaptureSequenceNumber() const override; void ResetFallbackToFirstNavigationSurface() override; void DidStopFlinging() override; std::unique_ptr<content::SyntheticGestureTarget> CreateSyntheticGestureTarget() override; + ui::Compositor *GetCompositor() override; // Overridden from ui::GestureProviderClient. void OnGestureEvent(const ui::GestureEventData& gesture) override; @@ -209,13 +219,12 @@ public: template<class T> void handlePointerEvent(T*); -#if defined(OS_MACOSX) +#if defined(OS_MAC) void SetActive(bool active) override { QT_NOT_YET_IMPLEMENTED } void SpeakSelection() override { QT_NOT_YET_IMPLEMENTED } void ShowDefinitionForSelection() override { QT_NOT_YET_IMPLEMENTED } -#endif // defined(OS_MACOSX) - - void UpdateNeedsBeginFramesInternal(); + void SetWindowFrameInScreen(const gfx::Rect&) override { QT_NOT_YET_IMPLEMENTED } +#endif // defined(OS_MAC) // Overridden from content::BrowserAccessibilityDelegate content::BrowserAccessibilityManager* CreateBrowserAccessibilityManager(content::BrowserAccessibilityDelegate* delegate, bool for_root_frame) override; @@ -225,6 +234,9 @@ public: // Overridden from content::RenderFrameMetadataProvider::Observer void OnRenderFrameMetadataChangedAfterActivation() override; + void OnRenderFrameMetadataChangedBeforeActivation(const cc::RenderFrameMetadata &) override {} + void OnRenderFrameSubmission() override {} + void OnLocalSurfaceIdChanged(const cc::RenderFrameMetadata &) override {} // Overridden from DisplayConsumer void scheduleUpdate() override; @@ -234,50 +246,51 @@ public: ui::TouchSelectionController *getTouchSelectionController() const { return m_touchSelectionController.get(); } TouchSelectionControllerClientQt *getTouchSelectionControllerClient() const { return m_touchSelectionControllerClient.get(); } - content::mojom::FrameInputHandler *getFrameInputHandler(); + blink::mojom::FrameWidgetInputHandler *getFrameWidgetInputHandler(); ui::TextInputType getTextInputType() const; private: friend class DelegatedFrameHostClientQt; void processMotionEvent(const ui::MotionEvent &motionEvent); - void clearPreviousTouchMotionState(); - QList<QTouchEvent::TouchPoint> mapTouchPointIds(const QList<QTouchEvent::TouchPoint> &inputPoints); + typedef QPair<int, QTouchEvent::TouchPoint> TouchPoint; + QList<TouchPoint> mapTouchPoints(const QList<QTouchEvent::TouchPoint> &input); bool IsPopup() const; void selectionChanged(); - content::RenderFrameHost *getFocusedFrameHost(); - void synchronizeVisualProperties(const base::Optional<viz::LocalSurfaceIdAllocation> &childSurfaceId); + void synchronizeVisualProperties(const base::Optional<viz::LocalSurfaceId> &childSurfaceId); void callUpdate(); + bool updateCursorFromResource(ui::mojom::CursorType type); + // Geometry of the view in screen DIPs. gfx::Rect m_viewRectInDips; // Geometry of the window, including frame, in screen DIPs. gfx::Rect m_windowRectInDips; - content::ScreenInfo m_screenInfo; + blink::ScreenInfo m_screenInfo; scoped_refptr<base::SingleThreadTaskRunner> m_taskRunner; + std::unique_ptr<content::CursorManager> m_cursorManager; ui::FilteredGestureProvider m_gestureProvider; base::TimeDelta m_eventsToNowDelta; bool m_sendMotionActionDown; bool m_touchMotionStarted; QMap<int, int> m_touchIdMapping; - QList<QTouchEvent::TouchPoint> m_previousTouchPoints; + QList<TouchPoint> m_previousTouchPoints; std::unique_ptr<RenderWidgetHostViewQtDelegate> m_delegate; + std::unique_ptr<GuestInputEventObserverQt> m_guestInputEventObserver; - const bool m_enableViz; bool m_visible; - bool m_needsBeginFrames; + bool m_deferredShow = false; DelegatedFrameHostClientQt m_delegatedFrameHostClient{this}; std::unique_ptr<content::DelegatedFrameHost> m_delegatedFrameHost; std::unique_ptr<ui::Layer> m_rootLayer; std::unique_ptr<ui::Compositor> m_uiCompositor; scoped_refptr<DisplayFrameSink> m_displayFrameSink; - std::unique_ptr<Compositor> m_compositor; LoadVisuallyCommittedState m_loadVisuallyCommittedState; QMetaObject::Connection m_adapterClientDestroyedConnection; @@ -287,6 +300,7 @@ private: bool m_imeInProgress; bool m_receivedEmptyImeEvent; QPoint m_previousMousePosition; + bool m_isMouseLocked; gfx::Vector2dF m_lastScrollOffset; gfx::SizeF m_lastContentsSize; @@ -315,6 +329,8 @@ private: gfx::SelectionBound m_selectionEnd; base::WeakPtrFactory<RenderWidgetHostViewQt> m_weakPtrFactory{this}; + + uint m_mouseButtonPressed = 0; }; } // namespace QtWebEngineCore diff --git a/src/core/render_widget_host_view_qt_delegate.h b/src/core/render_widget_host_view_qt_delegate.h index 4ee790ce9..5fda0eeb7 100644 --- a/src/core/render_widget_host_view_qt_delegate.h +++ b/src/core/render_widget_host_view_qt_delegate.h @@ -58,12 +58,11 @@ QT_BEGIN_NAMESPACE class QEvent; -class QSGLayer; +class QInputMethodEvent; class QSGNode; -class QSGRectangleNode; class QSGTexture; class QVariant; -class QInputMethodEvent; +class QWheelEvent; class QSGImageNode; @@ -100,9 +99,7 @@ public: virtual bool isVisible() const = 0; virtual QWindow* window() const = 0; virtual QSGTexture *createTextureFromImage(const QImage &) = 0; - virtual QSGLayer *createLayer() = 0; virtual QSGImageNode *createImageNode() = 0; - virtual QSGRectangleNode *createRectangleNode() = 0; virtual void update() = 0; virtual void updateCursor(const QCursor &) = 0; virtual void resize(int width, int height) = 0; @@ -111,6 +108,7 @@ public: virtual void setInputMethodHints(Qt::InputMethodHints hints) = 0; virtual void setClearColor(const QColor &color) = 0; virtual bool copySurface(const QRect &, const QSize &, QImage &) = 0; + virtual void unhandledWheelEvent(QWheelEvent *) {} }; } // namespace QtWebEngineCore diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp index b9b199087..d704e81b1 100644 --- a/src/core/renderer/content_renderer_client_qt.cpp +++ b/src/core/renderer/content_renderer_client_qt.cpp @@ -39,7 +39,6 @@ #include "renderer/content_renderer_client_qt.h" -#include "common/qt_messages.h" #include "extensions/buildflags/buildflags.h" #include "printing/buildflags/buildflags.h" #include "renderer/content_settings_observer_qt.h" @@ -51,22 +50,21 @@ #include "components/cdm/renderer/external_clear_key_key_system_properties.h" #include "components/cdm/renderer/widevine_key_system_properties.h" #include "components/error_page/common/error.h" -#include "components/error_page/common/error_page_params.h" #include "components/error_page/common/localized_error.h" -#include "components/network_hints/renderer/prescient_networking_dispatcher.h" +#include "components/network_hints/renderer/web_prescient_networking_impl.h" #if QT_CONFIG(webengine_printing_and_pdf) #include "components/printing/renderer/print_render_frame_helper.h" #endif -#include "components/visitedlink/renderer/visitedlink_slave.h" +#include "components/visitedlink/renderer/visitedlink_reader.h" #include "components/web_cache/renderer/web_cache_impl.h" #include "content/public/renderer/render_frame.h" #include "content/public/child/child_thread.h" -#include "content/public/common/service_manager_connection.h" -#include "content/public/common/simple_connection_filter.h" +#include "content/public/common/url_constants.h" #include "content/public/renderer/render_thread.h" #include "content/public/renderer/render_view.h" #include "media/base/key_system_properties.h" #include "media/media_buildflags.h" +#include "mojo/public/cpp/bindings/binder_map.h" #include "net/base/net_errors.h" #include "services/service_manager/public/cpp/connector.h" #include "services/service_manager/public/cpp/interface_provider.h" @@ -76,15 +74,15 @@ #include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/webui/jstemplate_builder.h" -#include "content/public/common/web_preferences.h" #if QT_CONFIG(webengine_printing_and_pdf) #include "renderer/print_web_view_helper_delegate_qt.h" #endif +#include "common/qt_messages.h" #include "renderer/render_frame_observer_qt.h" -#include "renderer/render_view_observer_qt.h" -#include "renderer/render_thread_observer_qt.h" +#include "renderer/web_engine_page_render_frame.h" +#include "renderer/render_configuration.h" #include "renderer/user_resource_controller.h" #if QT_CONFIG(webengine_webchannel) #include "renderer/web_channel_ipc_transport.h" @@ -93,8 +91,15 @@ #if BUILDFLAG(ENABLE_EXTENSIONS) #include "common/extensions/extensions_client_qt.h" #include "extensions/extensions_renderer_client_qt.h" +#include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.h" +#include "mojo/public/cpp/bindings/associated_remote.h" #endif //ENABLE_EXTENSIONS +#if BUILDFLAG(ENABLE_PLUGINS) +#include "plugins/loadable_plugin_placeholder_qt.h" +#include "content/common/frame_messages.h" +#endif // ENABLE_PLUGINS + #include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/cpp/connector.h" @@ -109,12 +114,17 @@ #include "third_party/widevine/cdm/widevine_cdm_common.h" #endif +#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) +#include "chrome/renderer/media/webrtc_logging_agent_impl.h" +#endif + +#include "web_engine_library_info.h" + namespace QtWebEngineCore { static const char kHttpErrorDomain[] = "http"; ContentRendererClientQt::ContentRendererClientQt() - : m_serviceBinding(this) { #if BUILDFLAG(ENABLE_EXTENSIONS) extensions::ExtensionsClient::Set(extensions::ExtensionsClientQt::GetInstance()); @@ -122,28 +132,19 @@ ContentRendererClientQt::ContentRendererClientQt() #endif } -ContentRendererClientQt::~ContentRendererClientQt() -{ -} +ContentRendererClientQt::~ContentRendererClientQt() {} void ContentRendererClientQt::RenderThreadStarted() { + base::i18n::SetICUDefaultLocale(WebEngineLibraryInfo::getApplicationLocale()); content::RenderThread *renderThread = content::RenderThread::Get(); - (void)GetConnector(); - m_renderThreadObserver.reset(new RenderThreadObserverQt()); - m_visitedLinkSlave.reset(new visitedlink::VisitedLinkSlave); + m_renderConfiguration.reset(new RenderConfiguration()); + m_userResourceController.reset(new UserResourceController()); + m_visitedLinkReader.reset(new visitedlink::VisitedLinkReader); m_webCacheImpl.reset(new web_cache::WebCacheImpl()); - m_prescientNetworkingDispatcher.reset(new network_hints::PrescientNetworkingDispatcher()); - - auto registry = std::make_unique<service_manager::BinderRegistry>(); - registry->AddInterface(m_visitedLinkSlave->GetBindCallback(), - base::ThreadTaskRunnerHandle::Get()); - content::ChildThread::Get()->GetServiceManagerConnection()->AddConnectionFilter( - std::make_unique<content::SimpleConnectionFilter>(std::move(registry))); - - renderThread->AddObserver(m_renderThreadObserver.data()); - renderThread->AddObserver(UserResourceController::instance()); + renderThread->AddObserver(m_renderConfiguration.data()); + renderThread->AddObserver(m_userResourceController.data()); #if QT_CONFIG(webengine_spellchecker) if (!m_spellCheck) @@ -151,43 +152,68 @@ void ContentRendererClientQt::RenderThreadStarted() #endif // Allow XMLHttpRequests from qrc to file. + // ### consider removing for Qt6 blink::WebURL qrc(blink::KURL("qrc:")); blink::WebString file(blink::WebString::FromASCII("file")); - blink::WebSecurityPolicy::AddOriginAccessAllowListEntry(qrc, file, blink::WebString(), 0, - network::mojom::CorsDomainMatchMode::kAllowSubdomains, - network::mojom::CorsPortMatchMode::kAllowAnyPort, - network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority); + blink::WebSecurityPolicy::AddOriginAccessAllowListEntry( + qrc, file, blink::WebString(), 0, network::mojom::CorsDomainMatchMode::kAllowSubdomains, + network::mojom::CorsPortMatchMode::kAllowAnyPort, + network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority); #if BUILDFLAG(ENABLE_EXTENSIONS) // Allow the pdf viewer extension to access chrome resources blink::WebURL pdfViewerExtension(blink::KURL("chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai")); blink::WebString chromeResources(blink::WebString::FromASCII("chrome")); - blink::WebSecurityPolicy::AddOriginAccessAllowListEntry(pdfViewerExtension, chromeResources, blink::WebString(), 0, - network::mojom::CorsDomainMatchMode::kAllowSubdomains, - network::mojom::CorsPortMatchMode::kAllowAnyPort, - network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority); + blink::WebSecurityPolicy::AddOriginAccessAllowListEntry( + pdfViewerExtension, chromeResources, blink::WebString(), 0, + network::mojom::CorsDomainMatchMode::kAllowSubdomains, network::mojom::CorsPortMatchMode::kAllowAnyPort, + network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority); ExtensionsRendererClientQt::GetInstance()->RenderThreadStarted(); #endif } -void ContentRendererClientQt::RenderViewCreated(content::RenderView* render_view) +void ContentRendererClientQt::ExposeInterfacesToBrowser(mojo::BinderMap* binders) { - // RenderViewObservers destroy themselves with their RenderView. - new RenderViewObserverQt(render_view); - UserResourceController::instance()->renderViewCreated(render_view); + binders->Add(m_visitedLinkReader->GetBindCallback(), base::SequencedTaskRunnerHandle::Get()); + + binders->Add(base::BindRepeating(&web_cache::WebCacheImpl::BindReceiver, + base::Unretained(m_webCacheImpl.get())), + base::SequencedTaskRunnerHandle::Get()); + +#if QT_CONFIG(webengine_spellchecker) + binders->Add(base::BindRepeating( + [](ContentRendererClientQt *client, + mojo::PendingReceiver<spellcheck::mojom::SpellChecker> receiver) { + if (!client->m_spellCheck) + client->InitSpellCheck(); + client->m_spellCheck->BindReceiver(std::move(receiver)); + }, this), + base::SequencedTaskRunnerHandle::Get()); +#endif + +#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) + binders->Add(base::BindRepeating( + [](ContentRendererClientQt *client, + mojo::PendingReceiver<chrome::mojom::WebRtcLoggingAgent> receiver) { + client->GetWebRtcLoggingAgent()->AddReceiver(std::move(receiver)); + }, this), + base::SequencedTaskRunnerHandle::Get()); +#endif } -void ContentRendererClientQt::RenderFrameCreated(content::RenderFrame* render_frame) +void ContentRendererClientQt::RenderFrameCreated(content::RenderFrame *render_frame) { QtWebEngineCore::RenderFrameObserverQt *render_frame_observer = new QtWebEngineCore::RenderFrameObserverQt(render_frame, m_webCacheImpl.data()); + if (render_frame->IsMainFrame()) { #if QT_CONFIG(webengine_webchannel) - if (render_frame->IsMainFrame()) new WebChannelIPCTransport(render_frame); #endif + new WebEnginePageRenderFrame(render_frame); + } - UserResourceController::instance()->renderFrameCreated(render_frame); + m_userResourceController->renderFrameCreated(render_frame); new QtWebEngineCore::ContentSettingsObserverQt(render_frame); @@ -195,11 +221,14 @@ void ContentRendererClientQt::RenderFrameCreated(content::RenderFrame* render_fr new SpellCheckProvider(render_frame, m_spellCheck.data(), this); #endif #if QT_CONFIG(webengine_printing_and_pdf) - new printing::PrintRenderFrameHelper( - render_frame, - base::WrapUnique(new PrintWebViewHelperDelegateQt())); + new printing::PrintRenderFrameHelper(render_frame, base::WrapUnique(new PrintWebViewHelperDelegateQt())); #endif // QT_CONFIG(webengine_printing_and_pdf) #if BUILDFLAG(ENABLE_EXTENSIONS) + blink::AssociatedInterfaceRegistry *associated_interfaces = render_frame_observer->associatedInterfaces(); + associated_interfaces->AddInterface(base::BindRepeating( + &extensions::MimeHandlerViewContainerManager::BindReceiver, + render_frame->GetRoutingID())); + auto registry = std::make_unique<service_manager::BinderRegistry>(); ExtensionsRendererClientQt::GetInstance()->RenderFrameCreated(render_frame, render_frame_observer->registry()); #endif @@ -220,7 +249,7 @@ void ContentRendererClientQt::RunScriptsAtDocumentEnd(content::RenderFrame *rend RenderFrameObserverQt *render_frame_observer = RenderFrameObserverQt::Get(render_frame); if (render_frame_observer && !render_frame_observer->isFrameDetached()) - UserResourceController::instance()->RunScriptsAtDocumentEnd(render_frame); + m_userResourceController->RunScriptsAtDocumentEnd(render_frame); #if BUILDFLAG(ENABLE_EXTENSIONS) ExtensionsRendererClientQt::GetInstance()->RunScriptsAtDocumentEnd(render_frame); @@ -246,38 +275,33 @@ bool ContentRendererClientQt::HasErrorPage(int httpStatusCode) return true; } -bool ContentRendererClientQt::ShouldSuppressErrorPage(content::RenderFrame *frame, const GURL &) -{ - return !(frame->GetWebkitPreferences().enable_error_page); -} - // To tap into the chromium localized strings. Ripped from the chrome layer (highly simplified). void ContentRendererClientQt::PrepareErrorPage(content::RenderFrame *renderFrame, const blink::WebURLError &web_error, const std::string &httpMethod, - bool ignoring_cache, std::string *errorHtml) { - Q_UNUSED(ignoring_cache); - GetNavigationErrorStringsInternal(renderFrame, httpMethod, - error_page::Error::NetError(web_error.url(), web_error.reason(), web_error.has_copy_in_cache()), - errorHtml); + GetNavigationErrorStringsInternal( + renderFrame, httpMethod, + error_page::Error::NetError((GURL)web_error.url(), web_error.reason(), net::ResolveErrorInfo(), web_error.has_copy_in_cache()), + errorHtml); } void ContentRendererClientQt::PrepareErrorPageForHttpStatusError(content::RenderFrame *renderFrame, const GURL &unreachable_url, const std::string &httpMethod, - bool ignoring_cache, int http_status, std::string *errorHtml) { - Q_UNUSED(ignoring_cache); GetNavigationErrorStringsInternal(renderFrame, httpMethod, error_page::Error::HttpError(unreachable_url, http_status), errorHtml); } -void ContentRendererClientQt::GetNavigationErrorStringsInternal(content::RenderFrame *renderFrame, const std::string &httpMethod, const error_page::Error &error, std::string *errorHtml) +void ContentRendererClientQt::GetNavigationErrorStringsInternal(content::RenderFrame *renderFrame, + const std::string &httpMethod, + const error_page::Error &error, + std::string *errorHtml) { Q_UNUSED(renderFrame) const bool isPost = QByteArray::fromStdString(httpMethod) == QByteArrayLiteral("POST"); @@ -291,14 +315,14 @@ void ContentRendererClientQt::GetNavigationErrorStringsInternal(content::RenderF // NetErrorHelper::GetErrorStringsForDnsProbe, but that one is harder to untangle. error_page::LocalizedError::PageState errorPageState = - error_page::LocalizedError::GetPageState( - error.reason(), error.domain(), error.url(), isPost, - error.stale_copy_in_cache(), false, RenderThreadObserverQt::is_incognito_process(), false, - false, locale, std::unique_ptr<error_page::ErrorPageParams>()); + error_page::LocalizedError::GetPageState( + error.reason(), error.domain(), error.url(), isPost, false, + error.stale_copy_in_cache(), false, + RenderConfiguration::is_incognito_process(), false, false, false, locale); resourceId = IDR_NET_ERROR_HTML; - std::string extracted_string = ui::ResourceBundle::GetSharedInstance().DecompressDataResource(resourceId); + std::string extracted_string = ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(resourceId); const base::StringPiece template_html(extracted_string.data(), extracted_string.size()); if (template_html.empty()) NOTREACHED() << "unable to load template. ID: " << resourceId; @@ -309,55 +333,87 @@ void ContentRendererClientQt::GetNavigationErrorStringsInternal(content::RenderF uint64_t ContentRendererClientQt::VisitedLinkHash(const char *canonicalUrl, size_t length) { - return m_visitedLinkSlave->ComputeURLFingerprint(canonicalUrl, length); + return m_visitedLinkReader->ComputeURLFingerprint(canonicalUrl, length); } bool ContentRendererClientQt::IsLinkVisited(uint64_t linkHash) { - return m_visitedLinkSlave->IsVisited(linkHash); + return m_visitedLinkReader->IsVisited(linkHash); +} + +std::unique_ptr<blink::WebPrescientNetworking> ContentRendererClientQt::CreatePrescientNetworking(content::RenderFrame *render_frame) +{ + return std::make_unique<network_hints::WebPrescientNetworkingImpl>(render_frame); } -blink::WebPrescientNetworking *ContentRendererClientQt::GetPrescientNetworking() +bool ContentRendererClientQt::IsPluginHandledExternally(content::RenderFrame *render_frame, + const blink::WebElement &plugin_element, + const GURL &original_url, + const std::string &original_mime_type) { - return m_prescientNetworkingDispatcher.get(); +#if BUILDFLAG(ENABLE_EXTENSIONS) && BUILDFLAG(ENABLE_PLUGINS) + bool found = false; + content::WebPluginInfo plugin_info; + std::string mime_type; + + render_frame->Send(new FrameHostMsg_GetPluginInfo(render_frame->GetRoutingID(), original_url, + render_frame->GetWebFrame()->Top()->GetSecurityOrigin(), + original_mime_type, &found, &plugin_info, &mime_type)); + + return extensions::MimeHandlerViewContainerManager::Get( + content::RenderFrame::FromWebFrame( + plugin_element.GetDocument().GetFrame()), + true /* create_if_does_not_exist */) + ->CreateFrameContainer(plugin_element, original_url, mime_type, plugin_info); +#else + return false; +#endif } -bool ContentRendererClientQt::OverrideCreatePlugin( - content::RenderFrame* render_frame, - const blink::WebPluginParams& params, blink::WebPlugin** plugin) +bool ContentRendererClientQt::OverrideCreatePlugin(content::RenderFrame *render_frame, + const blink::WebPluginParams ¶ms, + blink::WebPlugin **plugin) { #if BUILDFLAG(ENABLE_EXTENSIONS) if (!ExtensionsRendererClientQt::GetInstance()->OverrideCreatePlugin(render_frame, params)) return false; #endif //ENABLE_EXTENSIONS - return content::ContentRendererClient::OverrideCreatePlugin(render_frame, params, plugin); + +#if BUILDFLAG(ENABLE_PLUGINS) + content::WebPluginInfo info; + std::string mime_type; + bool found = false; + + render_frame->Send(new FrameHostMsg_GetPluginInfo(render_frame->GetRoutingID(), params.url, + render_frame->GetWebFrame()->Top()->GetSecurityOrigin(), + params.mime_type.Utf8(), &found, &info, &mime_type)); + if (!found) + *plugin = LoadablePluginPlaceholderQt::CreateLoadableMissingPlugin(render_frame, params)->plugin(); + else + *plugin = render_frame->CreatePlugin(info, params, nullptr); +#endif // BUILDFLAG(ENABLE_PLUGINS) + return true; } -content::BrowserPluginDelegate* ContentRendererClientQt::CreateBrowserPluginDelegate(content::RenderFrame *render_frame, - const content::WebPluginInfo &info, - const std::string &mime_type, - const GURL &original_url) +bool ContentRendererClientQt::IsOriginIsolatedPepperPlugin(const base::FilePath& plugin_path) { -#if BUILDFLAG(ENABLE_EXTENSIONS) - return ExtensionsRendererClientQt::GetInstance()->CreateBrowserPluginDelegate(render_frame, info, mime_type, original_url); -#else - return nullptr; -#endif + return plugin_path.value() == FILE_PATH_LITERAL("internal-pdf-viewer"); } -void ContentRendererClientQt::OnBindInterface(const service_manager::BindSourceInfo &remote_info, - const std::string& name, - mojo::ScopedMessagePipeHandle handle) +#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) +chrome::WebRtcLoggingAgentImpl *ContentRendererClientQt::GetWebRtcLoggingAgent() { - Q_UNUSED(remote_info); - m_registry.TryBindInterface(name, &handle); + if (!m_webrtcLoggingAgentImpl) { + m_webrtcLoggingAgentImpl = std::make_unique<chrome::WebRtcLoggingAgentImpl>(); + } + + return m_webrtcLoggingAgentImpl.get(); } +#endif // QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) void ContentRendererClientQt::GetInterface(const std::string &interface_name, mojo::ScopedMessagePipeHandle interface_pipe) { - m_serviceBinding.GetConnector()->BindInterface( - service_manager::ServiceFilter::ByName("qtwebengine"), - interface_name, std::move(interface_pipe)); + content::RenderThread::Get()->BindHostReceiver(mojo::GenericPendingReceiver(interface_name, std::move(interface_pipe))); } // The following is based on chrome/renderer/media/chrome_key_systems.cc: @@ -367,7 +423,7 @@ void ContentRendererClientQt::GetInterface(const std::string &interface_name, mo #if BUILDFLAG(ENABLE_LIBRARY_CDMS) // External Clear Key (used for testing). -static void AddExternalClearKey(std::vector<std::unique_ptr<media::KeySystemProperties>>* concrete_key_systems) +static void AddExternalClearKey(std::vector<std::unique_ptr<media::KeySystemProperties>> *concrete_key_systems) { // TODO(xhwang): Move these into an array so we can use a for loop to add // supported key systems below. @@ -403,57 +459,58 @@ static void AddExternalClearKey(std::vector<std::unique_ptr<media::KeySystemProp } concrete_key_systems->emplace_back( - new cdm::ExternalClearKeyProperties(kExternalClearKeyKeySystem)); + new cdm::ExternalClearKeyProperties(kExternalClearKeyKeySystem)); // Add support of decrypt-only mode in ClearKeyCdm. - concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( - kExternalClearKeyDecryptOnlyKeySystem)); + concrete_key_systems->emplace_back( + new cdm::ExternalClearKeyProperties(kExternalClearKeyDecryptOnlyKeySystem)); // A key system that triggers various types of messages in ClearKeyCdm. - concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( - kExternalClearKeyMessageTypeTestKeySystem)); + concrete_key_systems->emplace_back( + new cdm::ExternalClearKeyProperties(kExternalClearKeyMessageTypeTestKeySystem)); // A key system that triggers the FileIO test in ClearKeyCdm. - concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( - kExternalClearKeyFileIOTestKeySystem)); + concrete_key_systems->emplace_back( + new cdm::ExternalClearKeyProperties(kExternalClearKeyFileIOTestKeySystem)); // A key system that triggers the output protection test in ClearKeyCdm. - concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( - kExternalClearKeyOutputProtectionTestKeySystem)); + concrete_key_systems->emplace_back( + new cdm::ExternalClearKeyProperties(kExternalClearKeyOutputProtectionTestKeySystem)); // A key system that triggers the platform verification test in ClearKeyCdm. - concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( - kExternalClearKeyPlatformVerificationTestKeySystem)); + concrete_key_systems->emplace_back( + new cdm::ExternalClearKeyProperties(kExternalClearKeyPlatformVerificationTestKeySystem)); // A key system that Chrome thinks is supported by ClearKeyCdm, but actually // will be refused by ClearKeyCdm. This is to test the CDM initialization // failure case. - concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( - kExternalClearKeyInitializeFailKeySystem)); + concrete_key_systems->emplace_back( + new cdm::ExternalClearKeyProperties(kExternalClearKeyInitializeFailKeySystem)); // A key system that triggers a crash in ClearKeyCdm. - concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( - kExternalClearKeyCrashKeySystem)); + concrete_key_systems->emplace_back( + new cdm::ExternalClearKeyProperties(kExternalClearKeyCrashKeySystem)); // A key system that triggers the verify host files test in ClearKeyCdm. - concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( - kExternalClearKeyVerifyCdmHostTestKeySystem)); + concrete_key_systems->emplace_back( + new cdm::ExternalClearKeyProperties(kExternalClearKeyVerifyCdmHostTestKeySystem)); // A key system that fetches the Storage ID in ClearKeyCdm. - concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( - kExternalClearKeyStorageIdTestKeySystem)); + concrete_key_systems->emplace_back( + new cdm::ExternalClearKeyProperties(kExternalClearKeyStorageIdTestKeySystem)); // A key system that is registered with a different CDM GUID. - concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( - kExternalClearKeyDifferentGuidTestKeySystem)); + concrete_key_systems->emplace_back( + new cdm::ExternalClearKeyProperties(kExternalClearKeyDifferentGuidTestKeySystem)); // A key system that triggers CDM Proxy test in ClearKeyCdm. - concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( - kExternalClearKeyCdmProxyTestKeySystem)); + concrete_key_systems->emplace_back( + new cdm::ExternalClearKeyProperties(kExternalClearKeyCdmProxyTestKeySystem)); } #if BUILDFLAG(ENABLE_WIDEVINE) -static media::SupportedCodecs GetSupportedCodecs(const std::vector<media::VideoCodec> &supported_video_codecs, bool is_secure) +static media::SupportedCodecs GetSupportedCodecs(const std::vector<media::VideoCodec> &supported_video_codecs, + bool is_secure) { media::SupportedCodecs supported_codecs = media::EME_CODEC_NONE; @@ -469,7 +526,7 @@ static media::SupportedCodecs GetSupportedCodecs(const std::vector<media::VideoC supported_codecs |= media::EME_CODEC_FLAC; #if BUILDFLAG(USE_PROPRIETARY_CODECS) supported_codecs |= media::EME_CODEC_AAC; -#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) +#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) } // Video codecs are determined by what was registered for the CDM. @@ -486,7 +543,7 @@ static media::SupportedCodecs GetSupportedCodecs(const std::vector<media::VideoC case media::VideoCodec::kCodecH264: supported_codecs |= media::EME_CODEC_AVC1; break; -#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) +#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) default: DVLOG(1) << "Unexpected supported codec: " << GetCodecName(codec); break; @@ -505,13 +562,11 @@ static void AddWidevine(std::vector<std::unique_ptr<media::KeySystemProperties>> } // Codecs and encryption schemes. - auto codecs = - GetSupportedCodecs(capability->video_codecs, /*is_secure=*/false); - const auto& encryption_schemes = capability->encryption_schemes; + auto codecs = GetSupportedCodecs(capability->video_codecs, /*is_secure=*/false); + const auto &encryption_schemes = capability->encryption_schemes; auto hw_secure_codecs = GetSupportedCodecs(capability->hw_secure_video_codecs, /*is_secure=*/true); - const auto& hw_secure_encryption_schemes = - capability->hw_secure_encryption_schemes; + const auto &hw_secure_encryption_schemes = capability->hw_secure_encryption_schemes; // Robustness. using Robustness = cdm::WidevineKeySystemProperties::Robustness; @@ -562,34 +617,30 @@ void ContentRendererClientQt::AddSupportedKeySystems(std::vector<std::unique_ptr #if QT_CONFIG(webengine_spellchecker) void ContentRendererClientQt::InitSpellCheck() { - m_spellCheck.reset(new SpellCheck(&m_registry, this)); + m_spellCheck.reset(new SpellCheck(this)); } #endif void ContentRendererClientQt::WillSendRequest(blink::WebLocalFrame *frame, ui::PageTransition transition_type, const blink::WebURL &url, + const net::SiteForCookies &site_for_cookies, const url::Origin *initiator_origin, GURL *new_url, bool *attach_same_site_cookies) { #if BUILDFLAG(ENABLE_EXTENSIONS) - ExtensionsRendererClientQt::GetInstance()->WillSendRequest(frame, transition_type, url, initiator_origin, new_url, attach_same_site_cookies); + ExtensionsRendererClientQt::GetInstance()->WillSendRequest(frame, transition_type, url, /*site_for_cookies,*/ + initiator_origin, new_url, attach_same_site_cookies); if (!new_url->is_empty()) return; #endif - content::ContentRendererClient::WillSendRequest(frame, transition_type, url, initiator_origin, new_url, attach_same_site_cookies); -} - -void ContentRendererClientQt::CreateRendererService(service_manager::mojom::ServiceRequest service_request) -{ - DCHECK(!m_serviceBinding.is_bound()); - m_serviceBinding.Bind(std::move(service_request)); } -service_manager::Connector* ContentRendererClientQt::GetConnector() +bool ContentRendererClientQt::RequiresWebComponentsV0(const GURL &url) { - return m_serviceBinding.GetConnector(); + Q_UNUSED(url); + return false; } -} // namespace +} // namespace QtWebEngineCore diff --git a/src/core/renderer/content_renderer_client_qt.h b/src/core/renderer/content_renderer_client_qt.h index a13d16b5c..a0faec531 100644 --- a/src/core/renderer/content_renderer_client_qt.h +++ b/src/core/renderer/content_renderer_client_qt.h @@ -43,23 +43,25 @@ #include "content/public/renderer/content_renderer_client.h" #include "components/spellcheck/spellcheck_buildflags.h" #include "services/service_manager/public/cpp/binder_registry.h" -#include "services/service_manager/public/cpp/connector.h" #include "services/service_manager/public/cpp/local_interface_provider.h" -#include "services/service_manager/public/cpp/service.h" -#include "services/service_manager/public/cpp/service_binding.h" +#include "ppapi/buildflags/buildflags.h" + +#if BUILDFLAG(ENABLE_PLUGINS) +#include "third_party/blink/public/web/web_plugin_params.h" +#endif #include <QScopedPointer> -namespace error_page { -class Error; +namespace chrome { +class WebRtcLoggingAgentImpl; } -namespace network_hints { -class PrescientNetworkingDispatcher; +namespace error_page { +class Error; } namespace visitedlink { -class VisitedLinkSlave; +class VisitedLinkReader; } namespace web_cache { @@ -70,13 +72,17 @@ class WebCacheImpl; class SpellCheck; #endif -namespace QtWebEngineCore { +namespace content { +struct WebPluginInfo; +} -class RenderThreadObserverQt; +namespace QtWebEngineCore { -class ContentRendererClientQt : public content::ContentRendererClient - , public service_manager::Service - , public service_manager::LocalInterfaceProvider +class UserResourceController; +class RenderConfiguration; +class ContentRendererClientQt + : public content::ContentRendererClient + , public service_manager::LocalInterfaceProvider { public: ContentRendererClientQt(); @@ -84,73 +90,72 @@ public: // content::ContentRendererClient: void RenderThreadStarted() override; - void RenderViewCreated(content::RenderView *render_view) override; - void RenderFrameCreated(content::RenderFrame* render_frame) override; - bool ShouldSuppressErrorPage(content::RenderFrame *, const GURL &) override; + void ExposeInterfacesToBrowser(mojo::BinderMap* binders) override; + void RenderFrameCreated(content::RenderFrame *render_frame) override; bool HasErrorPage(int http_status_code) override; void PrepareErrorPage(content::RenderFrame *render_frame, const blink::WebURLError &error, const std::string &http_method, - bool ignoring_cache, std::string *error_html) override; void PrepareErrorPageForHttpStatusError(content::RenderFrame *render_frame, const GURL &unreachable_url, const std::string &http_method, - bool ignoring_cache, int http_status, std::string *error_html) override; uint64_t VisitedLinkHash(const char *canonical_url, size_t length) override; bool IsLinkVisited(uint64_t linkHash) override; - blink::WebPrescientNetworking* GetPrescientNetworking() override; - void AddSupportedKeySystems(std::vector<std::unique_ptr<media::KeySystemProperties>>* key_systems) override; + std::unique_ptr<blink::WebPrescientNetworking> CreatePrescientNetworking(content::RenderFrame *render_frame) override; + void AddSupportedKeySystems(std::vector<std::unique_ptr<media::KeySystemProperties>> *key_systems) override; void RunScriptsAtDocumentStart(content::RenderFrame *render_frame) override; void RunScriptsAtDocumentEnd(content::RenderFrame *render_frame) override; void RunScriptsAtDocumentIdle(content::RenderFrame *render_frame) override; - bool OverrideCreatePlugin(content::RenderFrame* render_frame, - const blink::WebPluginParams& params, blink::WebPlugin** plugin) override; - content::BrowserPluginDelegate* CreateBrowserPluginDelegate(content::RenderFrame* render_frame, - const content::WebPluginInfo& info, const std::string& mime_type, const GURL& original_url) override; + bool IsPluginHandledExternally(content::RenderFrame *embedder_frame, + const blink::WebElement &plugin_element, + const GURL &original_url, + const std::string &original_mime_type); + bool OverrideCreatePlugin(content::RenderFrame *render_frame, + const blink::WebPluginParams ¶ms, + blink::WebPlugin **plugin) override; + bool IsOriginIsolatedPepperPlugin(const base::FilePath& plugin_path) override; void WillSendRequest(blink::WebLocalFrame *frame, ui::PageTransition transition_type, const blink::WebURL &url, + const net::SiteForCookies &site_for_cookies, const url::Origin *initiator_origin, GURL *new_url, bool *attach_same_site_cookies) override; - void CreateRendererService(service_manager::mojom::ServiceRequest service_request) override; + bool RequiresWebComponentsV0(const GURL &url) override; + +#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) + chrome::WebRtcLoggingAgentImpl *GetWebRtcLoggingAgent(); +#endif + private: #if BUILDFLAG(ENABLE_SPELLCHECK) void InitSpellCheck(); #endif - service_manager::Connector *GetConnector(); - - // service_manager::Service: - void OnBindInterface(const service_manager::BindSourceInfo &remote_info, - const std::string &name, - mojo::ScopedMessagePipeHandle handle) override; - // service_manager::LocalInterfaceProvider: - void GetInterface(const std::string& name, mojo::ScopedMessagePipeHandle request_handle) override; + void GetInterface(const std::string &name, mojo::ScopedMessagePipeHandle request_handle) override; - void GetNavigationErrorStringsInternal(content::RenderFrame* renderFrame, const std::string &httpMethod, - const error_page::Error& error, std::string* errorHtml); + void GetNavigationErrorStringsInternal(content::RenderFrame *renderFrame, const std::string &httpMethod, + const error_page::Error &error, std::string *errorHtml); - QScopedPointer<RenderThreadObserverQt> m_renderThreadObserver; - QScopedPointer<visitedlink::VisitedLinkSlave> m_visitedLinkSlave; + QScopedPointer<RenderConfiguration> m_renderConfiguration; + QScopedPointer<UserResourceController> m_userResourceController; + QScopedPointer<visitedlink::VisitedLinkReader> m_visitedLinkReader; QScopedPointer<web_cache::WebCacheImpl> m_webCacheImpl; #if QT_CONFIG(webengine_spellchecker) QScopedPointer<SpellCheck> m_spellCheck; #endif - - service_manager::mojom::ConnectorRequest m_connectorRequest; - service_manager::ServiceBinding m_serviceBinding; - service_manager::BinderRegistry m_registry; - std::unique_ptr<network_hints::PrescientNetworkingDispatcher> m_prescientNetworkingDispatcher; +#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) + std::unique_ptr<chrome::WebRtcLoggingAgentImpl> m_webrtcLoggingAgentImpl; +#endif DISALLOW_COPY_AND_ASSIGN(ContentRendererClientQt); }; diff --git a/src/core/renderer/content_settings_observer_qt.cpp b/src/core/renderer/content_settings_observer_qt.cpp index a9e89dfee..18d52b50a 100644 --- a/src/core/renderer/content_settings_observer_qt.cpp +++ b/src/core/renderer/content_settings_observer_qt.cpp @@ -59,53 +59,48 @@ namespace { bool IsUniqueFrame(blink::WebFrame *frame) { - return frame->GetSecurityOrigin().IsUnique() || - frame->Top()->GetSecurityOrigin().IsUnique(); + return frame->GetSecurityOrigin().IsOpaque() || + frame->Top()->GetSecurityOrigin().IsOpaque(); } -} // namespace +} // namespace namespace QtWebEngineCore { ContentSettingsObserverQt::ContentSettingsObserverQt(content::RenderFrame *render_frame) - : content::RenderFrameObserver(render_frame) - , content::RenderFrameObserverTracker<ContentSettingsObserverQt>(render_frame) - , m_currentRequestId(0) + : content::RenderFrameObserver(render_frame) + , content::RenderFrameObserverTracker<ContentSettingsObserverQt>(render_frame) + , m_currentRequestId(0) { ClearBlockedContentSettings(); render_frame->GetWebFrame()->SetContentSettingsClient(this); } -ContentSettingsObserverQt::~ContentSettingsObserverQt() { -} +ContentSettingsObserverQt::~ContentSettingsObserverQt() {} -bool ContentSettingsObserverQt::OnMessageReceived(const IPC::Message& message) +bool ContentSettingsObserverQt::OnMessageReceived(const IPC::Message &message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(ContentSettingsObserverQt, message) - IPC_MESSAGE_HANDLER(QtWebEngineMsg_RequestFileSystemAccessAsyncResponse, - OnRequestFileSystemAccessAsyncResponse) - IPC_MESSAGE_UNHANDLED(handled = false) + IPC_MESSAGE_HANDLER(QtWebEngineMsg_RequestStorageAccessAsyncResponse, OnRequestStorageAccessAsyncResponse) + IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; } -void ContentSettingsObserverQt::DidCommitProvisionalLoad(bool is_same_document_navigation, - ui::PageTransition /*transition*/) +void ContentSettingsObserverQt::DidCommitProvisionalLoad(ui::PageTransition /*transition*/) { - blink::WebLocalFrame* frame = render_frame()->GetWebFrame(); + blink::WebLocalFrame *frame = render_frame()->GetWebFrame(); if (frame->Parent()) - return; // Not a top-level navigation. + return; // Not a top-level navigation. - if (!is_same_document_navigation) - ClearBlockedContentSettings(); + ClearBlockedContentSettings(); GURL url = frame->GetDocument().Url(); // If we start failing this DCHECK, please makes sure we don't regress // this bug: http://code.google.com/p/chromium/issues/detail?id=79304 - DCHECK(frame->GetDocument().GetSecurityOrigin().ToString() == "null" || - !url.SchemeIs(url::kDataScheme)); + DCHECK(frame->GetDocument().GetSecurityOrigin().ToString() == "null" || !url.SchemeIs(url::kDataScheme)); } void ContentSettingsObserverQt::OnDestruct() @@ -113,73 +108,51 @@ void ContentSettingsObserverQt::OnDestruct() delete this; } -bool ContentSettingsObserverQt::AllowDatabase() -{ - blink::WebFrame *frame = render_frame()->GetWebFrame(); - if (IsUniqueFrame(frame)) - return false; - - bool result = false; - Send(new QtWebEngineHostMsg_AllowDatabase( - routing_id(), url::Origin(frame->GetSecurityOrigin()).GetURL(), - url::Origin(frame->Top()->GetSecurityOrigin()).GetURL(), - &result)); - return result; -} - -void ContentSettingsObserverQt::RequestFileSystemAccessAsync(base::OnceCallback<void(bool)> callback) +void ContentSettingsObserverQt::AllowStorageAccess(StorageType storage_type, + base::OnceCallback<void(bool)> callback) { blink::WebFrame *frame = render_frame()->GetWebFrame(); if (IsUniqueFrame(frame)) { std::move(callback).Run(false); return; } + ++m_currentRequestId; bool inserted = m_permissionRequests.insert(std::make_pair(m_currentRequestId, std::move(callback))).second; // Verify there are no duplicate insertions. DCHECK(inserted); - Send(new QtWebEngineHostMsg_RequestFileSystemAccessAsync( - routing_id(), m_currentRequestId, - url::Origin(frame->GetSecurityOrigin()).GetURL(), - url::Origin(frame->Top()->GetSecurityOrigin()).GetURL())); + Send(new QtWebEngineHostMsg_RequestStorageAccessAsync(routing_id(), m_currentRequestId, + url::Origin(frame->GetSecurityOrigin()).GetURL(), + url::Origin(frame->Top()->GetSecurityOrigin()).GetURL(), + int(storage_type))); } -bool ContentSettingsObserverQt::AllowIndexedDB(const WebSecurityOrigin &origin) -{ - blink::WebFrame *frame = render_frame()->GetWebFrame(); - if (IsUniqueFrame(frame)) - return false; - - bool result = false; - Send(new QtWebEngineHostMsg_AllowIndexedDB( - routing_id(), url::Origin(origin).GetURL(), - url::Origin(frame->Top()->GetSecurityOrigin()).GetURL(), - &result)); - return result; -} - -bool ContentSettingsObserverQt::AllowStorage(bool local) +bool ContentSettingsObserverQt::AllowStorageAccessSync(StorageType storage_type) { blink::WebLocalFrame *frame = render_frame()->GetWebFrame(); if (IsUniqueFrame(frame)) return false; - StoragePermissionsKey key(url::Origin(frame->GetDocument().GetSecurityOrigin()).GetURL(), local); - const auto permissions = m_cachedStoragePermissions.find(key); - if (permissions != m_cachedStoragePermissions.end()) - return permissions->second; + bool sameOrigin = url::Origin(frame->Top()->GetSecurityOrigin()).IsSameOriginWith(url::Origin(frame->GetSecurityOrigin())); + StoragePermissionsKey key(url::Origin(frame->GetSecurityOrigin()).GetURL(), int(storage_type)); + if (sameOrigin) { + const auto permissions = m_cachedStoragePermissions.find(key); + if (permissions != m_cachedStoragePermissions.end()) + return permissions->second; + } bool result = false; - Send(new QtWebEngineHostMsg_AllowDOMStorage( - routing_id(), url::Origin(frame->GetSecurityOrigin()).GetURL(), - url::Origin(frame->Top()->GetSecurityOrigin()).GetURL(), local, &result)); - m_cachedStoragePermissions[key] = result; + Send(new QtWebEngineHostMsg_AllowStorageAccess(routing_id(), url::Origin(frame->GetSecurityOrigin()).GetURL(), + url::Origin(frame->Top()->GetSecurityOrigin()).GetURL(), + int(storage_type), &result)); + if (sameOrigin) + m_cachedStoragePermissions[key] = result; return result; } -void ContentSettingsObserverQt::OnRequestFileSystemAccessAsyncResponse(int request_id, bool allowed) +void ContentSettingsObserverQt::OnRequestStorageAccessAsyncResponse(int request_id, bool allowed) { auto it = m_permissionRequests.find(request_id); if (it == m_permissionRequests.end()) diff --git a/src/core/renderer/content_settings_observer_qt.h b/src/core/renderer/content_settings_observer_qt.h index 9c071aa3c..9268b4982 100644 --- a/src/core/renderer/content_settings_observer_qt.h +++ b/src/core/renderer/content_settings_observer_qt.h @@ -58,36 +58,33 @@ namespace QtWebEngineCore { // Handles blocking content per content settings for each RenderFrame. class ContentSettingsObserverQt - : public content::RenderFrameObserver - , public content::RenderFrameObserverTracker<ContentSettingsObserverQt> - , public blink::WebContentSettingsClient + : public content::RenderFrameObserver + , public content::RenderFrameObserverTracker<ContentSettingsObserverQt> + , public blink::WebContentSettingsClient { public: ContentSettingsObserverQt(content::RenderFrame *render_frame); ~ContentSettingsObserverQt() override; // blink::WebContentSettingsClient: - bool AllowDatabase() override; - void RequestFileSystemAccessAsync(base::OnceCallback<void(bool)> callback) override; - bool AllowIndexedDB(const blink::WebSecurityOrigin &origin) override; - bool AllowStorage(bool local) override; + void AllowStorageAccess(StorageType storage_type, + base::OnceCallback<void(bool)> callback) override; + bool AllowStorageAccessSync(StorageType storage_type) override; private: - // RenderFrameObserver implementation: bool OnMessageReceived(const IPC::Message &message) override; - void DidCommitProvisionalLoad(bool is_same_document_navigation, - ui::PageTransition transition) override; + void DidCommitProvisionalLoad(ui::PageTransition transition) override; void OnDestruct() override; // Message handlers. - void OnRequestFileSystemAccessAsyncResponse(int request_id, bool allowed); + void OnRequestStorageAccessAsyncResponse(int request_id, bool allowed); // Clears m_cachedStoragePermissions void ClearBlockedContentSettings(); // Caches the result of AllowStorage. - using StoragePermissionsKey = std::pair<GURL, bool>; + using StoragePermissionsKey = std::pair<GURL, int>; base::flat_map<StoragePermissionsKey, bool> m_cachedStoragePermissions; int m_currentRequestId; @@ -98,4 +95,4 @@ private: } // namespace QtWebEngineCore -#endif // RENDERER_CONTENT_SETTINGS_OBSERVER_QT_H +#endif // RENDERER_CONTENT_SETTINGS_OBSERVER_QT_H diff --git a/src/core/renderer/extensions/extensions_dispatcher_delegate_qt.cpp b/src/core/renderer/extensions/extensions_dispatcher_delegate_qt.cpp index 418429330..d49845f55 100644 --- a/src/core/renderer/extensions/extensions_dispatcher_delegate_qt.cpp +++ b/src/core/renderer/extensions/extensions_dispatcher_delegate_qt.cpp @@ -39,6 +39,9 @@ #include "extensions_dispatcher_delegate_qt.h" +#include "chrome/grit/renderer_resources.h" +#include "extensions/renderer/resource_bundle_source_map.h" + namespace QtWebEngineCore { ExtensionsDispatcherDelegateQt::ExtensionsDispatcherDelegateQt() @@ -49,4 +52,10 @@ ExtensionsDispatcherDelegateQt::~ExtensionsDispatcherDelegateQt() { } +void ExtensionsDispatcherDelegateQt::PopulateSourceMap(extensions::ResourceBundleSourceMap *source_map) +{ + // Custom binding for hangout services extension. + source_map->RegisterSource("webrtcDesktopCapturePrivate", IDR_WEBRTC_DESKTOP_CAPTURE_PRIVATE_CUSTOM_BINDINGS_JS); +} + } //namespace QtWebEngineCore diff --git a/src/core/renderer/extensions/extensions_dispatcher_delegate_qt.h b/src/core/renderer/extensions/extensions_dispatcher_delegate_qt.h index 25aa18e71..1a19bcbbb 100644 --- a/src/core/renderer/extensions/extensions_dispatcher_delegate_qt.h +++ b/src/core/renderer/extensions/extensions_dispatcher_delegate_qt.h @@ -52,6 +52,9 @@ public: ~ExtensionsDispatcherDelegateQt() override; private: + // extensions::DispatcherDelegate implementation. + void PopulateSourceMap(extensions::ResourceBundleSourceMap *source_map) override; + DISALLOW_COPY_AND_ASSIGN(ExtensionsDispatcherDelegateQt); }; diff --git a/src/core/renderer/extensions/extensions_renderer_client_qt.cpp b/src/core/renderer/extensions/extensions_renderer_client_qt.cpp index 7d4c9a83c..f72113018 100644 --- a/src/core/renderer/extensions/extensions_renderer_client_qt.cpp +++ b/src/core/renderer/extensions/extensions_renderer_client_qt.cpp @@ -45,7 +45,7 @@ #include "extensions_renderer_client_qt.h" #include "extensions_dispatcher_delegate_qt.h" -#include "renderer/render_thread_observer_qt.h" +#include "renderer/render_configuration.h" #include "renderer_permissions_policy_delegate_qt.h" #include "resource_request_policy_qt.h" @@ -88,7 +88,7 @@ ExtensionsRendererClientQt::~ExtensionsRendererClientQt() // Returns true if the current render process was launched incognito. bool ExtensionsRendererClientQt::IsIncognitoProcess() const { - return RenderThreadObserverQt::is_incognito_process(); + return RenderConfiguration::is_incognito_process(); } // Returns the lowest isolated world ID available to extensions. @@ -147,8 +147,6 @@ bool ExtensionsRendererClientQt::ExtensionAPIEnabledForServiceWorkerScript(const void ExtensionsRendererClientQt::RenderThreadStarted() { content::RenderThread *thread = content::RenderThread::Get(); - // ChromeRenderViewTest::SetUp() creates its own ExtensionDispatcher and - // injects it using SetExtensionDispatcher(). Don't overwrite it. if (!extension_dispatcher_) extension_dispatcher_.reset(new extensions::Dispatcher(std::make_unique<ExtensionsDispatcherDelegateQt>())); extension_dispatcher_->OnRenderThreadStarted(thread); @@ -200,16 +198,6 @@ bool ExtensionsRendererClientQt::ShouldFork(blink::WebLocalFrame *frame, return false; // TODO: Fix this to a sensible value } -content::BrowserPluginDelegate *ExtensionsRendererClientQt::CreateBrowserPluginDelegate(content::RenderFrame *render_frame, - const content::WebPluginInfo &info, - const std::string &mime_type, - const GURL &original_url) -{ - if (mime_type == content::kBrowserPluginMimeType) - return new extensions::ExtensionsGuestViewContainer(render_frame); - return new extensions::MimeHandlerViewContainer(render_frame, info, mime_type, original_url); -} - void ExtensionsRendererClientQt::RunScriptsAtDocumentStart(content::RenderFrame *render_frame) { extension_dispatcher_->RunScriptsAtDocumentStart(render_frame); diff --git a/src/core/renderer/extensions/extensions_renderer_client_qt.h b/src/core/renderer/extensions/extensions_renderer_client_qt.h index 87e324213..85cc7bf2d 100644 --- a/src/core/renderer/extensions/extensions_renderer_client_qt.h +++ b/src/core/renderer/extensions/extensions_renderer_client_qt.h @@ -108,10 +108,6 @@ public: bool is_initial_navigation, bool is_server_redirect, bool *send_referrer); - static content::BrowserPluginDelegate *CreateBrowserPluginDelegate(content::RenderFrame *render_frame, - const content::WebPluginInfo &info, - const std::string &mime_type, - const GURL &original_url); bool ExtensionAPIEnabledForServiceWorkerScript(const GURL &scope, const GURL &script_url) const override; diff --git a/src/core/renderer/pepper/pepper_renderer_host_factory_qt.cpp b/src/core/renderer/pepper/pepper_renderer_host_factory_qt.cpp index 33c744f13..1b9de4d4d 100644 --- a/src/core/renderer/pepper/pepper_renderer_host_factory_qt.cpp +++ b/src/core/renderer/pepper/pepper_renderer_host_factory_qt.cpp @@ -48,6 +48,7 @@ #include "base/memory/ptr_util.h" #include "chrome/renderer/pepper/pepper_flash_font_file_host.h" +#include "chrome/renderer/pepper/pepper_uma_host.h" #if QT_CONFIG(webengine_printing_and_pdf) #include "components/pdf/renderer/pepper_pdf_host.h" #endif // QT_CONFIG(webengine_printing_and_pdf) @@ -127,6 +128,14 @@ std::unique_ptr<ppapi::host::ResourceHost> PepperRendererHostFactoryQt::CreateRe } } #endif // QT_CONFIG(webengine_printing_and_pdf) + + // Create a default ResourceHost for this message type to suppress + // "Failed to create PPAPI resource host" console error message. + switch (message.type()) { + case PpapiHostMsg_UMA_Create::ID: + return std::make_unique<ppapi::host::ResourceHost>(host_->GetPpapiHost(), instance, resource); + } + return nullptr; } diff --git a/src/core/renderer/plugins/loadable_plugin_placeholder_qt.cpp b/src/core/renderer/plugins/loadable_plugin_placeholder_qt.cpp new file mode 100644 index 000000000..9dc5fbd94 --- /dev/null +++ b/src/core/renderer/plugins/loadable_plugin_placeholder_qt.cpp @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "loadable_plugin_placeholder_qt.h" +#include "qtwebenginecoreglobal_p.h" + +#include "content/public/renderer/render_frame.h" +#include "components/strings/grit/components_strings.h" +#include "chrome/grit/renderer_resources.h" +#include "gin/handle.h" +#include "gin/wrappable.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/base/webui/jstemplate_builder.h" + +namespace QtWebEngineCore { + +// static +gin::WrapperInfo LoadablePluginPlaceholderQt::kWrapperInfo = {gin::kEmbedderNativeGin}; + +LoadablePluginPlaceholderQt::LoadablePluginPlaceholderQt(content::RenderFrame* render_frame, + const blink::WebPluginParams& params, + const std::string& html_data, + const base::string16& title) + : plugins::LoadablePluginPlaceholder(render_frame, params, html_data) + , context_menu_request_id_(0) +{} + +LoadablePluginPlaceholderQt::~LoadablePluginPlaceholderQt() +{ + if (context_menu_request_id_ && render_frame()) + render_frame()->CancelContextMenu(context_menu_request_id_); +} + +// TODO(bauerb): Move this method to NonLoadablePluginPlaceholder? +// static +LoadablePluginPlaceholderQt* LoadablePluginPlaceholderQt::CreateLoadableMissingPlugin(content::RenderFrame* render_frame, + const blink::WebPluginParams& params) +{ + std::string template_html(ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(IDR_BLOCKED_PLUGIN_HTML)); + + base::DictionaryValue values; + values.SetString("name", ""); + values.SetString("message", l10n_util::GetStringUTF8(IDS_PLUGIN_NOT_SUPPORTED)); + + const std::string html_data = webui::GetI18nTemplateHtml(template_html, &values); + + // Will destroy itself when its WebViewPlugin is going away. + return new LoadablePluginPlaceholderQt(render_frame, params, html_data, params.mime_type.Utf16()); +} + +blink::WebPlugin* LoadablePluginPlaceholderQt::CreatePlugin() +{ + QT_NOT_YET_IMPLEMENTED + return nullptr; +} + +v8::Local<v8::Value> LoadablePluginPlaceholderQt::GetV8Handle(v8::Isolate* isolate) +{ + return gin::CreateHandle(isolate, this).ToV8(); +} + +} // namespace QtWebEngineCore diff --git a/src/core/net/custom_protocol_handler.h b/src/core/renderer/plugins/loadable_plugin_placeholder_qt.h index 625afc1d5..7bcad2d96 100644 --- a/src/core/net/custom_protocol_handler.h +++ b/src/core/renderer/plugins/loadable_plugin_placeholder_qt.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWebEngine module of the Qt Toolkit. @@ -37,53 +37,48 @@ ** ****************************************************************************/ -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -#ifndef CUSTOM_PROTOCOL_HANDLER_H_ -#define CUSTOM_PROTOCOL_HANDLER_H_ +#ifndef LOADALBLE_PLUGIN_PLACEHOLDER_QT_H +#define LOADALBLE_PLUGIN_PLACEHOLDER_QT_H -#include "qtwebenginecoreglobal_p.h" -#include "net/url_request/url_request_job_factory.h" - -#include <QtCore/QByteArray> -#include <QtCore/QObject> -#include <QtCore/QPointer> - -QT_FORWARD_DECLARE_CLASS(QIODevice) - -namespace net { -class NetworkDelegate; -class URLRequestJob; -} // namespace +#include "base/macros.h" +#include "components/plugins/renderer/loadable_plugin_placeholder.h" namespace QtWebEngineCore { -class ProfileAdapter; - -// Implements a ProtocolHandler for custom URL schemes. -// If |network_delegate_| is NULL then all file requests will fail with ERR_ACCESS_DENIED. -class Q_WEBENGINECORE_PRIVATE_EXPORT CustomProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler +class LoadablePluginPlaceholderQt final : public plugins::LoadablePluginPlaceholder + , public gin::Wrappable<LoadablePluginPlaceholderQt> { - public: - CustomProtocolHandler(QPointer<ProfileAdapter> profileAdapter); + static gin::WrapperInfo kWrapperInfo; - net::URLRequestJob *MaybeCreateJob(net::URLRequest *request, net::NetworkDelegate *networkDelegate) const override; + // Creates a new WebViewPlugin with a MissingPlugin as a delegate. + static LoadablePluginPlaceholderQt* CreateLoadableMissingPlugin(content::RenderFrame* render_frame, + const blink::WebPluginParams& params); private: - DISALLOW_COPY_AND_ASSIGN(CustomProtocolHandler); - QPointer<ProfileAdapter> m_profileAdapter; + LoadablePluginPlaceholderQt(content::RenderFrame* render_frame, + const blink::WebPluginParams& params, + const std::string& html_data, + const base::string16& title); + ~LoadablePluginPlaceholderQt() override; + + // content::LoadablePluginPlaceholder overrides. + blink::WebPlugin* CreatePlugin() override; + void OnBlockedContent(content::RenderFrame::PeripheralContentStatus status, + bool is_same_origin) override {} + + // WebViewPlugin::Delegate (via PluginPlaceholder) methods: + v8::Local<v8::Value> GetV8Handle(v8::Isolate* isolate) override; + + int context_menu_request_id_; // Nonzero when request pending. + + DISALLOW_COPY_AND_ASSIGN(LoadablePluginPlaceholderQt); }; -} // namespace +} // namespace QtWebEngineCore -#endif // CUSTOM_PROTOCOL_HANDLER_H_ +#endif // LOADALBLE_PLUGIN_PLACEHOLDER_QT_H diff --git a/src/core/renderer/print_web_view_helper_delegate_qt.cpp b/src/core/renderer/print_web_view_helper_delegate_qt.cpp index 67cdd6b66..5dcfaafd6 100644 --- a/src/core/renderer/print_web_view_helper_delegate_qt.cpp +++ b/src/core/renderer/print_web_view_helper_delegate_qt.cpp @@ -43,36 +43,42 @@ #include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_view.h" +#include "extensions/buildflags/buildflags.h" #include "extensions/common/constants.h" #include "third_party/blink/public/web/web_document.h" #include "third_party/blink/public/web/web_element.h" #include "third_party/blink/public/web/web_local_frame.h" +#if BUILDFLAG(ENABLE_EXTENSIONS) +#include "chrome/common/webui_url_constants.h" +#include "extensions/common/constants.h" +#endif // BUILDFLAG(ENABLE_EXTENSIONS) + #include "print_web_view_helper_delegate_qt.h" #include "web_engine_library_info.h" namespace QtWebEngineCore { -PrintWebViewHelperDelegateQt::~PrintWebViewHelperDelegateQt() -{ - -} - -bool PrintWebViewHelperDelegateQt::CancelPrerender(content::RenderFrame *) -{ - return false; -} +PrintWebViewHelperDelegateQt::~PrintWebViewHelperDelegateQt() {} -blink::WebElement PrintWebViewHelperDelegateQt::GetPdfElement(blink::WebLocalFrame* frame) +blink::WebElement PrintWebViewHelperDelegateQt::GetPdfElement(blink::WebLocalFrame *frame) { +#if BUILDFLAG(ENABLE_EXTENSIONS) GURL url = frame->GetDocument().Url(); - if (url.SchemeIs(extensions::kExtensionScheme) && url.host() == extension_misc::kPdfExtensionId) - { + bool inside_print_preview = url.GetOrigin() == chrome::kChromeUIPrintURL; + bool inside_pdf_extension = url.SchemeIs(extensions::kExtensionScheme) && + url.host_piece() == extension_misc::kPdfExtensionId; + if (inside_print_preview || inside_pdf_extension) { // <object> with id="plugin" is created in - // chrome/browser/resources/pdf/pdf.js. - auto plugin_element = frame->GetDocument().GetElementById("plugin"); - CHECK(!plugin_element.IsNull()); - return plugin_element; + // chrome/browser/resources/pdf/pdf_viewer_base.js. + auto viewer_element = frame->GetDocument().GetElementById("viewer"); + if (!viewer_element.IsNull() && !viewer_element.ShadowRoot().IsNull()) { + auto plugin_element = viewer_element.ShadowRoot().QuerySelector("#plugin"); + if (!plugin_element.IsNull()) + return plugin_element; + } + NOTREACHED(); } +#endif // BUILDFLAG(ENABLE_EXTENSIONS) return blink::WebElement(); } @@ -81,7 +87,7 @@ bool PrintWebViewHelperDelegateQt::IsPrintPreviewEnabled() return true; } -bool PrintWebViewHelperDelegateQt::OverridePrint(blink::WebLocalFrame* frame) +bool PrintWebViewHelperDelegateQt::OverridePrint(blink::WebLocalFrame *frame) { return false; } diff --git a/src/core/renderer/print_web_view_helper_delegate_qt.h b/src/core/renderer/print_web_view_helper_delegate_qt.h index e3020922f..2cbc171a6 100644 --- a/src/core/renderer/print_web_view_helper_delegate_qt.h +++ b/src/core/renderer/print_web_view_helper_delegate_qt.h @@ -57,15 +57,12 @@ class PrintWebViewHelperDelegateQt : public printing::PrintRenderFrameHelper::De public: ~PrintWebViewHelperDelegateQt() override; - bool CancelPrerender(content::RenderFrame* render_frame) override; - - blink::WebElement GetPdfElement(blink::WebLocalFrame* frame) override; + blink::WebElement GetPdfElement(blink::WebLocalFrame *frame) override; bool IsPrintPreviewEnabled() override; - bool OverridePrint(blink::WebLocalFrame* frame) override; -}; // class PrintWebViewHelperDelegateQt + bool OverridePrint(blink::WebLocalFrame *frame) override; +}; // class PrintWebViewHelperDelegateQt } #endif // PRINT_WEB_VIEW_HELPER_DELEGATE_QT_H - diff --git a/src/core/renderer/render_thread_observer_qt.cpp b/src/core/renderer/render_configuration.cpp index 64b9fd961..ef9da7af7 100644 --- a/src/core/renderer/render_thread_observer_qt.cpp +++ b/src/core/renderer/render_configuration.cpp @@ -42,32 +42,37 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "renderer/render_thread_observer_qt.h" - +#include "renderer/render_configuration.h" +#include "user_resource_controller.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" namespace QtWebEngineCore { -bool RenderThreadObserverQt::m_isIncognitoProcess = false; +bool RenderConfiguration::m_isIncognitoProcess = false; -void RenderThreadObserverQt::RegisterMojoInterfaces(blink::AssociatedInterfaceRegistry *associated_interfaces) +void RenderConfiguration::RegisterMojoInterfaces( + blink::AssociatedInterfaceRegistry *associated_interfaces) { - associated_interfaces->AddInterface(base::Bind(&RenderThreadObserverQt::OnRendererConfigurationAssociatedRequest, base::Unretained(this))); + associated_interfaces->AddInterface( + base::Bind(&RenderConfiguration::OnRendererConfigurationAssociatedRequest, + base::Unretained(this))); } -void RenderThreadObserverQt::UnregisterMojoInterfaces(blink::AssociatedInterfaceRegistry *associated_interfaces) +void RenderConfiguration::UnregisterMojoInterfaces( + blink::AssociatedInterfaceRegistry *associated_interfaces) { associated_interfaces->RemoveInterface(qtwebengine::mojom::RendererConfiguration::Name_); } -void RenderThreadObserverQt::SetInitialConfiguration(bool is_incognito_process) +void RenderConfiguration::SetInitialConfiguration(bool is_incognito_process) { m_isIncognitoProcess = is_incognito_process; } -void RenderThreadObserverQt::OnRendererConfigurationAssociatedRequest(qtwebengine::mojom::RendererConfigurationAssociatedRequest request) +void RenderConfiguration::OnRendererConfigurationAssociatedRequest( + mojo::PendingAssociatedReceiver<qtwebengine::mojom::RendererConfiguration> receiver) { - m_rendererConfigurationBindings.AddBinding(this, std::move(request)); + m_rendererConfigurationReceivers.Add(this, std::move(receiver)); } } // namespace diff --git a/src/core/renderer/render_thread_observer_qt.h b/src/core/renderer/render_configuration.h index 29b842ab4..138a85bdc 100644 --- a/src/core/renderer/render_thread_observer_qt.h +++ b/src/core/renderer/render_configuration.h @@ -37,21 +37,22 @@ ** ****************************************************************************/ -#ifndef RENDER_THREAD_OBSERVER_QT_H -#define RENDER_THREAD_OBSERVER_QT_H +#ifndef RENDER_CONFIGURATION_H +#define RENDER_CONFIGURATION_H #include "content/public/renderer/render_thread_observer.h" -#include "mojo/public/cpp/bindings/associated_binding_set.h" +#include "mojo/public/cpp/bindings/associated_receiver_set.h" +#include "mojo/public/cpp/bindings/pending_associated_receiver.h" #include "qtwebengine/common/renderer_configuration.mojom.h" namespace QtWebEngineCore { -class RenderThreadObserverQt : public content::RenderThreadObserver, - public qtwebengine::mojom::RendererConfiguration { +class RenderConfiguration : public content::RenderThreadObserver, + public qtwebengine::mojom::RendererConfiguration +{ public: - - RenderThreadObserverQt() = default; - ~RenderThreadObserverQt() override = default; + RenderConfiguration() = default; + ~RenderConfiguration() override = default; static bool is_incognito_process() { return m_isIncognitoProcess; } @@ -63,15 +64,17 @@ private: // qtwebengine::mojom::RendererConfiguration: void SetInitialConfiguration(bool is_incognito_process) override; - void OnRendererConfigurationAssociatedRequest(qtwebengine::mojom::RendererConfigurationAssociatedRequest request); + void OnRendererConfigurationAssociatedRequest( + mojo::PendingAssociatedReceiver<qtwebengine::mojom::RendererConfiguration> receiver); static bool m_isIncognitoProcess; - mojo::AssociatedBindingSet<qtwebengine::mojom::RendererConfiguration> m_rendererConfigurationBindings; + mojo::AssociatedReceiverSet<qtwebengine::mojom::RendererConfiguration> + m_rendererConfigurationReceivers; - DISALLOW_COPY_AND_ASSIGN(RenderThreadObserverQt); + DISALLOW_COPY_AND_ASSIGN(RenderConfiguration); }; } // namespace QtWebEngineCore -#endif // RENDER_THREAD_OBSERVER_QT_H +#endif // RENDER_CONFIGURATION_H diff --git a/src/core/renderer/render_frame_observer_qt.cpp b/src/core/renderer/render_frame_observer_qt.cpp index c48ef3b5c..77d325f3c 100644 --- a/src/core/renderer/render_frame_observer_qt.cpp +++ b/src/core/renderer/render_frame_observer_qt.cpp @@ -55,34 +55,35 @@ namespace QtWebEngineCore { -RenderFrameObserverQt::RenderFrameObserverQt(content::RenderFrame* render_frame, - web_cache::WebCacheImpl* web_cache_impl) +RenderFrameObserverQt::RenderFrameObserverQt(content::RenderFrame *render_frame, web_cache::WebCacheImpl *web_cache_impl) : RenderFrameObserver(render_frame) , RenderFrameObserverTracker<RenderFrameObserverQt>(render_frame) , m_isFrameDetached(false) , m_web_cache_impl(web_cache_impl) -{ -} +{} -RenderFrameObserverQt::~RenderFrameObserverQt() -{ -} +RenderFrameObserverQt::~RenderFrameObserverQt() {} -void RenderFrameObserverQt::OnDestruct() { +void RenderFrameObserverQt::OnDestruct() +{ delete this; } #if QT_CONFIG(webengine_pepper_plugins) -void RenderFrameObserverQt::DidCreatePepperPlugin(content::RendererPpapiHost* host) +void RenderFrameObserverQt::DidCreatePepperPlugin(content::RendererPpapiHost *host) { - host->GetPpapiHost()->AddHostFactoryFilter( - base::WrapUnique(new PepperRendererHostFactoryQt(host))); - host->GetPpapiHost()->AddInstanceMessageFilter( - base::WrapUnique(new PepperSharedMemoryMessageFilter(host))); + host->GetPpapiHost()->AddHostFactoryFilter(base::WrapUnique(new PepperRendererHostFactoryQt(host))); + host->GetPpapiHost()->AddInstanceMessageFilter(base::WrapUnique(new PepperSharedMemoryMessageFilter(host))); } #endif -void RenderFrameObserverQt::FrameDetached() +bool RenderFrameObserverQt::OnAssociatedInterfaceRequestForFrame(const std::string &interface_name, + mojo::ScopedInterfaceEndpointHandle *handle) +{ + return m_associated_interfaces.TryBindInterface(interface_name, handle); +} + +void RenderFrameObserverQt::WillDetach() { m_isFrameDetached = true; } diff --git a/src/core/renderer/render_frame_observer_qt.h b/src/core/renderer/render_frame_observer_qt.h index fb9fd3869..8803dde89 100644 --- a/src/core/renderer/render_frame_observer_qt.h +++ b/src/core/renderer/render_frame_observer_qt.h @@ -46,6 +46,7 @@ #include "content/public/renderer/render_frame_observer_tracker.h" #include "ppapi/buildflags/buildflags.h" #include "services/service_manager/public/cpp/binder_registry.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" namespace content { class RenderFrame; @@ -57,23 +58,28 @@ class WebCacheImpl; namespace QtWebEngineCore { class RenderFrameObserverQt - : public content::RenderFrameObserver - , public content::RenderFrameObserverTracker<RenderFrameObserverQt> + : public content::RenderFrameObserver + , public content::RenderFrameObserverTracker<RenderFrameObserverQt> { public: - explicit RenderFrameObserverQt(content::RenderFrame* render_frame, - web_cache::WebCacheImpl* web_cache_impl); + explicit RenderFrameObserverQt(content::RenderFrame *render_frame, web_cache::WebCacheImpl *web_cache_impl); ~RenderFrameObserverQt(); #if QT_CONFIG(webengine_pepper_plugins) - void DidCreatePepperPlugin(content::RendererPpapiHost* host) override; + void DidCreatePepperPlugin(content::RendererPpapiHost *host) override; #endif + bool OnAssociatedInterfaceRequestForFrame( + const std::string &interface_name, + mojo::ScopedInterfaceEndpointHandle *handle) override; void OnDestruct() override; - void FrameDetached() override; + void WillDetach() override; bool isFrameDetached() const; - service_manager::BinderRegistry* registry() { return ®istry_; } + service_manager::BinderRegistry *registry() { return ®istry_; } + blink::AssociatedInterfaceRegistry *associatedInterfaces() { + return &m_associated_interfaces; + } private: DISALLOW_COPY_AND_ASSIGN(RenderFrameObserverQt); @@ -82,6 +88,7 @@ private: bool m_isFrameDetached; service_manager::BinderRegistry registry_; + blink::AssociatedInterfaceRegistry m_associated_interfaces; web_cache::WebCacheImpl *m_web_cache_impl; }; diff --git a/src/core/renderer/render_view_observer_qt.h b/src/core/renderer/render_view_observer_qt.h deleted file mode 100644 index a878eebe8..000000000 --- a/src/core/renderer/render_view_observer_qt.h +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef RENDER_VIEW_OBSERVER_QT_H -#define RENDER_VIEW_OBSERVER_QT_H - -#include "content/public/renderer/render_view_observer.h" - -#include <QtGlobal> - -class RenderViewObserverQt : public content::RenderViewObserver { -public: - RenderViewObserverQt(content::RenderView* render_view); - -private: - void onFetchDocumentMarkup(quint64 requestId); - void onFetchDocumentInnerText(quint64 requestId); - void onSetBackgroundColor(quint32 color); - - void OnDestruct() override; - - bool OnMessageReceived(const IPC::Message& message) override; - - DISALLOW_COPY_AND_ASSIGN(RenderViewObserverQt); -}; - -#endif // RENDER_VIEW_OBSERVER_QT_H diff --git a/src/core/renderer/user_resource_controller.cpp b/src/core/renderer/user_resource_controller.cpp index 2613d262e..c7b220fe6 100644 --- a/src/core/renderer/user_resource_controller.cpp +++ b/src/core/renderer/user_resource_controller.cpp @@ -52,9 +52,12 @@ #include "third_party/blink/public/web/web_script_source.h" #include "third_party/blink/public/web/web_view.h" #include "v8/include/v8.h" +#include "mojo/public/cpp/bindings/associated_receiver.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" #include "common/qt_messages.h" -#include "common/user_script_data.h" +#include "qtwebengine/userscript/user_script_data.h" #include "type_conversion.h" #include "user_script.h" @@ -62,9 +65,9 @@ #include <bitset> -Q_GLOBAL_STATIC(UserResourceController, qt_webengine_userResourceController) +namespace QtWebEngineCore { -static content::RenderView * const globalScriptsIndex = 0; +static content::RenderFrame *const globalScriptsIndex = nullptr; // Scripts meant to run after the load event will be run 500ms after DOMContentLoaded if the load event doesn't come within that delay. static const int afterLoadTimeout = 500; @@ -74,7 +77,8 @@ static int validUserScriptSchemes() return URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS | URLPattern::SCHEME_FILE | URLPattern::SCHEME_QRC; } -static bool regexMatchesURL(const std::string &pat, const GURL &url) { +static bool regexMatchesURL(const std::string &pat, const GURL &url) +{ QRegularExpression qre(QtWebEngineCore::toQt(pat)); qre.setPatternOptions(QRegularExpression::CaseInsensitiveOption); if (!qre.isValid()) @@ -96,7 +100,8 @@ static bool includeRuleMatchesURL(const std::string &pat, const GURL &url) return false; } -static bool scriptMatchesURL(const UserScriptData &scriptData, const GURL &url) { +static bool scriptMatchesURL(const QtWebEngineCore::UserScriptData &scriptData, const GURL &url) +{ // Logic taken from Chromium (extensions/common/user_script.cc) bool matchFound; if (!scriptData.urlPatterns.empty()) { @@ -130,42 +135,51 @@ static bool scriptMatchesURL(const UserScriptData &scriptData, const GURL &url) return true; } -class UserResourceController::RenderFrameObserverHelper : public content::RenderFrameObserver +// using UserScriptDataPtr = mojo::StructPtr<qtwebengine::mojom::UserScriptData>; + +class UserResourceController::RenderFrameObserverHelper + : public content::RenderFrameObserver, + public qtwebengine::mojom::UserResourceControllerRenderFrame { public: - RenderFrameObserverHelper(content::RenderFrame* render_frame); + RenderFrameObserverHelper(content::RenderFrame *render_frame, + UserResourceController *controller); + void BindReceiver( + mojo::PendingAssociatedReceiver<qtwebengine::mojom::UserResourceControllerRenderFrame> + receiver); private: // RenderFrameObserver implementation. - void DidCommitProvisionalLoad(bool is_same_document_navigation, ui::PageTransition transition) override; + void DidCommitProvisionalLoad(ui::PageTransition transition) override; void DidFinishDocumentLoad() override; void DidFinishLoad() override; - void FrameDetached() override; + void WillDetach() override; void OnDestruct() override; - bool OnMessageReceived(const IPC::Message& message) override; - - void onUserScriptAdded(const UserScriptData &); - void onUserScriptRemoved(const UserScriptData &); - void onScriptsCleared(); + void AddScript(const QtWebEngineCore::UserScriptData &data) override; + void RemoveScript(const QtWebEngineCore::UserScriptData &data) override; + void ClearScripts() override; class Runner; QScopedPointer<Runner> m_runner; + mojo::AssociatedReceiver<qtwebengine::mojom::UserResourceControllerRenderFrame> m_binding; + UserResourceController *m_userResourceController; }; // Helper class to create WeakPtrs so the AfterLoad tasks can be canceled and to // avoid running scripts more than once per injection point. -class UserResourceController::RenderFrameObserverHelper::Runner : public base::SupportsWeakPtr<Runner> { +class UserResourceController::RenderFrameObserverHelper::Runner : public base::SupportsWeakPtr<Runner> +{ public: - explicit Runner(blink::WebLocalFrame *frame) - : m_frame(frame) + explicit Runner(blink::WebLocalFrame *frame, UserResourceController *controller) + : m_frame(frame), m_userResourceController(controller) { } - void run(UserScriptData::InjectionPoint p) + void run(QtWebEngineCore::UserScriptData::InjectionPoint p) { DCHECK_LT(p, m_ran.size()); if (!m_ran[p]) { - UserResourceController::instance()->runScripts(p, m_frame); + m_userResourceController->runScripts(p, m_frame); m_ran[p] = true; } } @@ -173,36 +187,23 @@ public: private: blink::WebLocalFrame *m_frame; std::bitset<3> m_ran; + UserResourceController *m_userResourceController; }; -// Used only for script cleanup on RenderView destruction. -class UserResourceController::RenderViewObserverHelper : public content::RenderViewObserver -{ -public: - RenderViewObserverHelper(content::RenderView* render_view); -private: - // RenderViewObserver implementation. - void OnDestruct() override; -}; - -void UserResourceController::runScripts(UserScriptData::InjectionPoint p, blink::WebLocalFrame *frame) +void UserResourceController::runScripts(QtWebEngineCore::UserScriptData::InjectionPoint p, + blink::WebLocalFrame *frame) { content::RenderFrame *renderFrame = content::RenderFrame::FromWebFrame(frame); if (!renderFrame) return; const bool isMainFrame = renderFrame->IsMainFrame(); - content::RenderView *renderView = renderFrame->GetRenderView(); - if (!renderView) - return; - - QList<uint64_t> scriptsToRun = m_viewUserScriptMap.value(0).toList(); - scriptsToRun.append(m_viewUserScriptMap.value(renderView).toList()); + QList<uint64_t> scriptsToRun = m_frameUserScriptMap.value(globalScriptsIndex).toList(); + scriptsToRun.append(m_frameUserScriptMap.value(renderFrame).toList()); for (uint64_t id : qAsConst(scriptsToRun)) { - const UserScriptData &script = m_scripts.value(id); - if (script.injectionPoint != p - || (!script.injectForSubframes && !isMainFrame)) + const QtWebEngineCore::UserScriptData &script = m_scripts.value(id); + if (script.injectionPoint != p || (!script.injectForSubframes && !isMainFrame)) continue; if (!scriptMatchesURL(script, frame->GetDocument().Url())) continue; @@ -216,34 +217,40 @@ void UserResourceController::runScripts(UserScriptData::InjectionPoint p, blink: void UserResourceController::RunScriptsAtDocumentEnd(content::RenderFrame *render_frame) { - runScripts(UserScriptData::DocumentLoadFinished, render_frame->GetWebFrame()); + runScripts(QtWebEngineCore::UserScriptData::DocumentLoadFinished, render_frame->GetWebFrame()); } -UserResourceController::RenderFrameObserverHelper::RenderFrameObserverHelper(content::RenderFrame *render_frame) +UserResourceController::RenderFrameObserverHelper::RenderFrameObserverHelper( + content::RenderFrame *render_frame, UserResourceController *controller) : content::RenderFrameObserver(render_frame) + , m_binding(this) + , m_userResourceController(controller) { + render_frame->GetAssociatedInterfaceRegistry()->AddInterface( + base::BindRepeating(&UserResourceController::RenderFrameObserverHelper::BindReceiver, + base::Unretained(this))); } -UserResourceController::RenderViewObserverHelper::RenderViewObserverHelper(content::RenderView *render_view) - : content::RenderViewObserver(render_view) + +void UserResourceController::RenderFrameObserverHelper::BindReceiver( + mojo::PendingAssociatedReceiver<qtwebengine::mojom::UserResourceControllerRenderFrame> + receiver) { + m_binding.Bind(std::move(receiver)); } -void UserResourceController::RenderFrameObserverHelper::DidCommitProvisionalLoad(bool is_same_document_navigation, - ui::PageTransition /*transitionbool*/) +void UserResourceController::RenderFrameObserverHelper::DidCommitProvisionalLoad(ui::PageTransition /*transition*/) { - if (is_same_document_navigation) - return; - // We are almost ready to run scripts. We still have to wait until the host // process has been notified of the DidCommitProvisionalLoad event to ensure // that the WebChannelTransportHost is ready to receive messages. - m_runner.reset(new Runner(render_frame()->GetWebFrame())); + m_runner.reset(new Runner(render_frame()->GetWebFrame(), m_userResourceController)); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, - base::BindOnce(&Runner::run, m_runner->AsWeakPtr(), UserScriptData::DocumentElementCreation)); + base::BindOnce(&Runner::run, m_runner->AsWeakPtr(), + QtWebEngineCore::UserScriptData::DocumentElementCreation)); } void UserResourceController::RenderFrameObserverHelper::DidFinishDocumentLoad() @@ -252,89 +259,61 @@ void UserResourceController::RenderFrameObserverHelper::DidFinishDocumentLoad() // called instead of DidCommitProvisionalLoad). if (m_runner) base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::BindOnce(&Runner::run, m_runner->AsWeakPtr(), UserScriptData::AfterLoad), - base::TimeDelta::FromMilliseconds(afterLoadTimeout)); - + FROM_HERE, + base::BindOnce(&Runner::run, m_runner->AsWeakPtr(), + QtWebEngineCore::UserScriptData::AfterLoad), + base::TimeDelta::FromMilliseconds(afterLoadTimeout)); } void UserResourceController::RenderFrameObserverHelper::DidFinishLoad() { if (m_runner) base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce(&Runner::run, m_runner->AsWeakPtr(), UserScriptData::AfterLoad)); + FROM_HERE, + base::BindOnce(&Runner::run, m_runner->AsWeakPtr(), + QtWebEngineCore::UserScriptData::AfterLoad)); } -void UserResourceController::RenderFrameObserverHelper::FrameDetached() +void UserResourceController::RenderFrameObserverHelper::WillDetach() { m_runner.reset(); } void UserResourceController::RenderFrameObserverHelper::OnDestruct() { + if (content::RenderFrame *frame = render_frame()) { + m_userResourceController->renderFrameDestroyed(frame); + } delete this; } -void UserResourceController::RenderViewObserverHelper::OnDestruct() -{ - // Remove all scripts associated with the render view. - if (content::RenderView *view = render_view()) - UserResourceController::instance()->renderViewDestroyed(view); - delete this; -} - -bool UserResourceController::RenderFrameObserverHelper::OnMessageReceived(const IPC::Message &message) -{ - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(UserResourceController::RenderFrameObserverHelper, message) - IPC_MESSAGE_HANDLER(RenderFrameObserverHelper_AddScript, onUserScriptAdded) - IPC_MESSAGE_HANDLER(RenderFrameObserverHelper_RemoveScript, onUserScriptRemoved) - IPC_MESSAGE_HANDLER(RenderFrameObserverHelper_ClearScripts, onScriptsCleared) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; -} - -void UserResourceController::RenderFrameObserverHelper::onUserScriptAdded(const UserScriptData &script) +void UserResourceController::RenderFrameObserverHelper::AddScript( + const QtWebEngineCore::UserScriptData &script) { if (content::RenderFrame *frame = render_frame()) - if (content::RenderView *view = frame->GetRenderView()) - UserResourceController::instance()->addScriptForView(script, view); + m_userResourceController->addScriptForFrame(script, frame); } -void UserResourceController::RenderFrameObserverHelper::onUserScriptRemoved(const UserScriptData &script) +void UserResourceController::RenderFrameObserverHelper::RemoveScript( + const QtWebEngineCore::UserScriptData &script) { if (content::RenderFrame *frame = render_frame()) - if (content::RenderView *view = frame->GetRenderView()) - UserResourceController::instance()->removeScriptForView(script, view); + m_userResourceController->removeScriptForFrame(script, frame); } -void UserResourceController::RenderFrameObserverHelper::onScriptsCleared() +void UserResourceController::RenderFrameObserverHelper::ClearScripts() { if (content::RenderFrame *frame = render_frame()) - if (content::RenderView *view = frame->GetRenderView()) - UserResourceController::instance()->clearScriptsForView(view); -} - -UserResourceController *UserResourceController::instance() -{ - return qt_webengine_userResourceController(); + m_userResourceController->clearScriptsForFrame(frame); } -bool UserResourceController::OnControlMessageReceived(const IPC::Message &message) +void UserResourceController::BindReceiver( + mojo::PendingAssociatedReceiver<qtwebengine::mojom::UserResourceController> receiver) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(UserResourceController, message) - IPC_MESSAGE_HANDLER(UserResourceController_AddScript, onAddScript) - IPC_MESSAGE_HANDLER(UserResourceController_RemoveScript, onRemoveScript) - IPC_MESSAGE_HANDLER(UserResourceController_ClearScripts, onClearScripts) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; + m_binding.Bind(std::move(receiver)); } -UserResourceController::UserResourceController() +UserResourceController::UserResourceController() : m_binding(this) { #if !defined(QT_NO_DEBUG) || defined(QT_FORCE_ASSERTS) static bool onlyCalledOnce = true; @@ -346,69 +325,79 @@ UserResourceController::UserResourceController() void UserResourceController::renderFrameCreated(content::RenderFrame *renderFrame) { // Will destroy itself when the RenderFrame is destroyed. - new RenderFrameObserverHelper(renderFrame); + new RenderFrameObserverHelper(renderFrame, this); } -void UserResourceController::renderViewCreated(content::RenderView *renderView) +void UserResourceController::renderFrameDestroyed(content::RenderFrame *renderFrame) { - // Will destroy itself when the RenderView is destroyed. - new RenderViewObserverHelper(renderView); -} - -void UserResourceController::renderViewDestroyed(content::RenderView *renderView) -{ - ViewUserScriptMap::iterator it = m_viewUserScriptMap.find(renderView); - if (it == m_viewUserScriptMap.end()) // ASSERT maybe? + FrameUserScriptMap::iterator it = m_frameUserScriptMap.find(renderFrame); + if (it == m_frameUserScriptMap.end()) // ASSERT maybe? return; for (uint64_t id : qAsConst(it.value())) { m_scripts.remove(id); } - m_viewUserScriptMap.remove(renderView); + m_frameUserScriptMap.remove(renderFrame); } -void UserResourceController::addScriptForView(const UserScriptData &script, content::RenderView *view) +void UserResourceController::addScriptForFrame(const QtWebEngineCore::UserScriptData &script, + content::RenderFrame *frame) { - ViewUserScriptMap::iterator it = m_viewUserScriptMap.find(view); - if (it == m_viewUserScriptMap.end()) - it = m_viewUserScriptMap.insert(view, UserScriptSet()); + FrameUserScriptMap::iterator it = m_frameUserScriptMap.find(frame); + if (it == m_frameUserScriptMap.end()) + it = m_frameUserScriptMap.insert(frame, UserScriptSet()); (*it).insert(script.scriptId); m_scripts.insert(script.scriptId, script); } -void UserResourceController::removeScriptForView(const UserScriptData &script, content::RenderView *view) +void UserResourceController::removeScriptForFrame(const QtWebEngineCore::UserScriptData &script, + content::RenderFrame *frame) { - ViewUserScriptMap::iterator it = m_viewUserScriptMap.find(view); - if (it == m_viewUserScriptMap.end()) + FrameUserScriptMap::iterator it = m_frameUserScriptMap.find(frame); + if (it == m_frameUserScriptMap.end()) return; (*it).remove(script.scriptId); m_scripts.remove(script.scriptId); } -void UserResourceController::clearScriptsForView(content::RenderView *view) +void UserResourceController::clearScriptsForFrame(content::RenderFrame *frame) { - ViewUserScriptMap::iterator it = m_viewUserScriptMap.find(view); - if (it == m_viewUserScriptMap.end()) + FrameUserScriptMap::iterator it = m_frameUserScriptMap.find(frame); + if (it == m_frameUserScriptMap.end()) return; for (uint64_t id : qAsConst(it.value())) m_scripts.remove(id); - m_viewUserScriptMap.remove(view); + m_frameUserScriptMap.remove(frame); +} + +void UserResourceController::AddScript(const QtWebEngineCore::UserScriptData &script) +{ + addScriptForFrame(script, globalScriptsIndex); +} + +void UserResourceController::RemoveScript(const QtWebEngineCore::UserScriptData &script) +{ + removeScriptForFrame(script, globalScriptsIndex); } -void UserResourceController::onAddScript(const UserScriptData &script) +void UserResourceController::ClearScripts() { - addScriptForView(script, globalScriptsIndex); + clearScriptsForFrame(globalScriptsIndex); } -void UserResourceController::onRemoveScript(const UserScriptData &script) +void UserResourceController::RegisterMojoInterfaces( + blink::AssociatedInterfaceRegistry *associated_interfaces) { - removeScriptForView(script, globalScriptsIndex); + associated_interfaces->AddInterface( + base::Bind(&UserResourceController::BindReceiver, base::Unretained(this))); } -void UserResourceController::onClearScripts() +void UserResourceController::UnregisterMojoInterfaces( + blink::AssociatedInterfaceRegistry *associated_interfaces) { - clearScriptsForView(globalScriptsIndex); + associated_interfaces->RemoveInterface(qtwebengine::mojom::UserResourceController::Name_); } +} // namespace diff --git a/src/core/renderer/user_resource_controller.h b/src/core/renderer/user_resource_controller.h index 0b5e0a0c6..6c79d96fc 100644 --- a/src/core/renderer/user_resource_controller.h +++ b/src/core/renderer/user_resource_controller.h @@ -41,8 +41,9 @@ #define USER_RESOURCE_CONTROLLER_H #include "content/public/renderer/render_thread_observer.h" - -#include "common/user_script_data.h" +#include "qtwebengine/userscript/userscript.mojom.h" +#include "qtwebengine/userscript/user_script_data.h" +#include "mojo/public/cpp/bindings/associated_receiver.h" #include <QtCore/QHash> #include <QtCore/QSet> @@ -56,41 +57,46 @@ class RenderFrame; class RenderView; } -class UserResourceController : public content::RenderThreadObserver { +namespace QtWebEngineCore { + +class UserResourceController : public content::RenderThreadObserver, + qtwebengine::mojom::UserResourceController +{ public: - static UserResourceController *instance(); UserResourceController(); void renderFrameCreated(content::RenderFrame *); - void renderViewCreated(content::RenderView *); - void renderViewDestroyed(content::RenderView *renderView); - void addScriptForView(const UserScriptData &, content::RenderView *); - void removeScriptForView(const UserScriptData &, content::RenderView *); - void clearScriptsForView(content::RenderView *); + void renderFrameDestroyed(content::RenderFrame *); + void addScriptForFrame(const QtWebEngineCore::UserScriptData &, content::RenderFrame *); + void removeScriptForFrame(const QtWebEngineCore::UserScriptData &, content::RenderFrame *); + void clearScriptsForFrame(content::RenderFrame *); void RunScriptsAtDocumentEnd(content::RenderFrame *render_frame); + void BindReceiver( + mojo::PendingAssociatedReceiver<qtwebengine::mojom::UserResourceController> receiver); private: Q_DISABLE_COPY(UserResourceController) + // content::RenderThreadObserver: + void RegisterMojoInterfaces(blink::AssociatedInterfaceRegistry *associated_interfaces) override; + void UnregisterMojoInterfaces(blink::AssociatedInterfaceRegistry *associated_interfaces) override; + class RenderFrameObserverHelper; class RenderViewObserverHelper; - // RenderProcessObserver implementation. - bool OnControlMessageReceived(const IPC::Message &message) override; + void AddScript(const QtWebEngineCore::UserScriptData &data) override; + void RemoveScript(const QtWebEngineCore::UserScriptData &data) override; + void ClearScripts() override; - void onAddScript(const UserScriptData &); - void onRemoveScript(const UserScriptData &); - void onClearScripts(); - - void runScripts(UserScriptData::InjectionPoint, blink::WebLocalFrame *); + void runScripts(QtWebEngineCore::UserScriptData::InjectionPoint, blink::WebLocalFrame *); typedef QSet<uint64_t> UserScriptSet; - typedef QHash<const content::RenderView *, UserScriptSet> ViewUserScriptMap; - ViewUserScriptMap m_viewUserScriptMap; - QHash<uint64_t, UserScriptData> m_scripts; - + typedef QHash<const content::RenderFrame *, UserScriptSet> FrameUserScriptMap; + FrameUserScriptMap m_frameUserScriptMap; + QHash<uint64_t, QtWebEngineCore::UserScriptData> m_scripts; + mojo::AssociatedReceiver<qtwebengine::mojom::UserResourceController> m_binding; friend class RenderFrameObserverHelper; }; - +} // namespace #endif // USER_RESOURCE_CONTROLLER_H diff --git a/src/core/renderer/web_channel_ipc_transport.cpp b/src/core/renderer/web_channel_ipc_transport.cpp index 108686068..520c492ea 100644 --- a/src/core/renderer/web_channel_ipc_transport.cpp +++ b/src/core/renderer/web_channel_ipc_transport.cpp @@ -61,18 +61,21 @@ namespace QtWebEngineCore { -class WebChannelTransport : public gin::Wrappable<WebChannelTransport> { +class WebChannelTransport : public gin::Wrappable<WebChannelTransport> +{ public: static gin::WrapperInfo kWrapperInfo; static void Install(blink::WebLocalFrame *frame, uint worldId); static void Uninstall(blink::WebLocalFrame *frame, uint worldId); + private: WebChannelTransport() {} void NativeQtSendMessage(gin::Arguments *args); // gin::WrappableBase gin::ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate *isolate) override; - + mojo::AssociatedRemote<qtwebchannel::mojom::WebChannelTransportHost> m_remote; + content::RenderFrame *m_renderFrame = nullptr; DISALLOW_COPY_AND_ASSIGN(WebChannelTransport); }; @@ -152,9 +155,7 @@ void WebChannelTransport::NativeQtSendMessage(gin::Arguments *args) v8::Local<v8::String> jsonString = v8::Local<v8::String>::Cast(jsonValue); QByteArray json(jsonString->Utf8Length(isolate), 0); - jsonString->WriteUtf8(isolate, - json.data(), json.size(), - nullptr, v8::String::REPLACE_INVALID_UTF8); + jsonString->WriteUtf8(isolate, json.data(), json.size(), nullptr, v8::String::REPLACE_INVALID_UTF8); QJsonParseError error; QJsonDocument doc = QJsonDocument::fromJson(json, &error); @@ -165,30 +166,36 @@ void WebChannelTransport::NativeQtSendMessage(gin::Arguments *args) int size = 0; const char *rawData = doc.rawData(&size); - qtwebchannel::mojom::WebChannelTransportHostAssociatedPtr webChannelTransport; - renderFrame->GetRemoteAssociatedInterfaces()->GetInterface(&webChannelTransport); - webChannelTransport->DispatchWebChannelMessage(std::vector<uint8_t>(rawData, rawData + size)); + + if (!m_remote) { + renderFrame->GetRemoteAssociatedInterfaces()->GetInterface(&m_remote); + m_renderFrame = renderFrame; + } + DCHECK(renderFrame == m_renderFrame); + + m_remote->DispatchWebChannelMessage(std::vector<uint8_t>(rawData, rawData + size)); } gin::ObjectTemplateBuilder WebChannelTransport::GetObjectTemplateBuilder(v8::Isolate *isolate) { - return gin::Wrappable<WebChannelTransport>::GetObjectTemplateBuilder(isolate) - .SetMethod("send", &WebChannelTransport::NativeQtSendMessage); + return gin::Wrappable<WebChannelTransport>::GetObjectTemplateBuilder(isolate).SetMethod( + "send", &WebChannelTransport::NativeQtSendMessage); } WebChannelIPCTransport::WebChannelIPCTransport(content::RenderFrame *renderFrame) : content::RenderFrameObserver(renderFrame) , m_worldId(0) , m_worldInitialized(false) + , m_binding(this) { renderFrame->GetAssociatedInterfaceRegistry()->AddInterface( - base::Bind(&WebChannelIPCTransport::BindRequest, base::Unretained(this))); + base::BindRepeating(&WebChannelIPCTransport::BindReceiver, base::Unretained(this))); } -void WebChannelIPCTransport::BindRequest( - qtwebchannel::mojom::WebChannelTransportRenderAssociatedRequest request) { - - m_binding.AddBinding(this, std::move(request)); +void WebChannelIPCTransport::BindReceiver( + mojo::PendingAssociatedReceiver<qtwebchannel::mojom::WebChannelTransportRender> receiver) +{ + m_binding.Bind(std::move(receiver)); } void WebChannelIPCTransport::SetWorldId(uint32_t worldId) @@ -208,7 +215,7 @@ void WebChannelIPCTransport::SetWorldId(uint32_t worldId) void WebChannelIPCTransport::ResetWorldId() { - if (m_worldInitialized && m_canUseContext) + if (m_worldInitialized && m_canUseContext) WebChannelTransport::Uninstall(render_frame()->GetWebFrame(), m_worldId); m_worldInitialized = false; @@ -222,8 +229,8 @@ void WebChannelIPCTransport::DispatchWebChannelMessage(const std::vector<uint8_t if (!m_canUseContext) return; - QJsonDocument doc = QJsonDocument::fromRawData(reinterpret_cast<const char *>(binaryJson.data()), - binaryJson.size(), QJsonDocument::BypassValidation); + QJsonDocument doc = QJsonDocument::fromRawData(reinterpret_cast<const char *>(binaryJson.data()), binaryJson.size(), + QJsonDocument::BypassValidation); DCHECK(doc.isObject()); QByteArray json = doc.toJson(QJsonDocument::Compact); @@ -242,22 +249,23 @@ void WebChannelIPCTransport::DispatchWebChannelMessage(const std::vector<uint8_t if (qtObjectValue.IsEmpty() || !qtObjectValue.ToLocalChecked()->IsObject()) return; v8::Local<v8::Object> qtObject = v8::Local<v8::Object>::Cast(qtObjectValue.ToLocalChecked()); - v8::MaybeLocal<v8::Value> webChannelObjectValue(qtObject->Get(context, gin::StringToV8(isolate, "webChannelTransport"))); + v8::MaybeLocal<v8::Value> webChannelObjectValue( + qtObject->Get(context, gin::StringToV8(isolate, "webChannelTransport"))); if (webChannelObjectValue.IsEmpty() || !webChannelObjectValue.ToLocalChecked()->IsObject()) return; v8::Local<v8::Object> webChannelObject = v8::Local<v8::Object>::Cast(webChannelObjectValue.ToLocalChecked()); v8::MaybeLocal<v8::Value> callbackValue(webChannelObject->Get(context, gin::StringToV8(isolate, "onmessage"))); if (callbackValue.IsEmpty() || !callbackValue.ToLocalChecked()->IsFunction()) { - LOG(WARNING) << "onmessage is not a callable property of qt.webChannelTransport. Some things might not work as expected."; + LOG(WARNING) << "onmessage is not a callable property of qt.webChannelTransport. Some things might not work as " + "expected."; return; } v8::Local<v8::Object> messageObject(v8::Object::New(isolate)); v8::Maybe<bool> wasSet = messageObject->DefineOwnProperty( - context, - v8::String::NewFromUtf8(isolate, "data").ToLocalChecked(), - v8::String::NewFromUtf8(isolate, json.constData(), v8::NewStringType::kNormal, json.size()).ToLocalChecked(), - v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete)); + context, v8::String::NewFromUtf8(isolate, "data").ToLocalChecked(), + v8::String::NewFromUtf8(isolate, json.constData(), v8::NewStringType::kNormal, json.size()).ToLocalChecked(), + v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete)); DCHECK(!wasSet.IsNothing() && wasSet.FromJust()); v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(callbackValue.ToLocalChecked()); diff --git a/src/core/renderer/web_channel_ipc_transport.h b/src/core/renderer/web_channel_ipc_transport.h index 178c20ed1..4bed5f26d 100644 --- a/src/core/renderer/web_channel_ipc_transport.h +++ b/src/core/renderer/web_channel_ipc_transport.h @@ -42,15 +42,18 @@ #include "content/public/renderer/render_frame_observer.h" #include "services/service_manager/public/cpp/binder_registry.h" -#include "mojo/public/cpp/bindings/associated_binding_set.h" +#include "mojo/public/cpp/bindings/associated_receiver_set.h" +#include "mojo/public/cpp/bindings/pending_associated_receiver.h" #include "qtwebengine/browser/qtwebchannel.mojom.h" #include <QtCore/qglobal.h> namespace QtWebEngineCore { -class WebChannelIPCTransport: private content::RenderFrameObserver, - public qtwebchannel::mojom::WebChannelTransportRender { +class WebChannelIPCTransport + : private content::RenderFrameObserver + , public qtwebchannel::mojom::WebChannelTransportRender +{ public: WebChannelIPCTransport(content::RenderFrame *); @@ -58,13 +61,13 @@ private: // qtwebchannel::mojom::WebChannelTransportRender void SetWorldId(uint32_t worldId) override; void ResetWorldId() override; - void DispatchWebChannelMessage(const std::vector<uint8_t>& binaryJson, uint32_t worldId) override; + void DispatchWebChannelMessage(const std::vector<uint8_t> &binaryJson, uint32_t worldId) override; // RenderFrameObserver void WillReleaseScriptContext(v8::Local<v8::Context> context, int worldId) override; void DidClearWindowObject() override; void OnDestruct() override; - void BindRequest(qtwebchannel::mojom::WebChannelTransportRenderAssociatedRequest request); + void BindReceiver(mojo::PendingAssociatedReceiver<qtwebchannel::mojom::WebChannelTransportRender> receiver); private: // The worldId from our WebChannelIPCTransportHost or empty when there is no @@ -73,7 +76,7 @@ private: bool m_worldInitialized; // True means it's currently OK to manipulate the frame's script context. bool m_canUseContext = false; - mojo::AssociatedBindingSet<qtwebchannel::mojom::WebChannelTransportRender> m_binding; + mojo::AssociatedReceiver<qtwebchannel::mojom::WebChannelTransportRender> m_binding; }; } // namespace diff --git a/src/core/renderer/render_view_observer_qt.cpp b/src/core/renderer/web_engine_page_render_frame.cpp index 7e7c7bdf8..add1788d6 100644 --- a/src/core/renderer/render_view_observer_qt.cpp +++ b/src/core/renderer/web_engine_page_render_frame.cpp @@ -37,11 +37,11 @@ ** ****************************************************************************/ -#include "renderer/render_view_observer_qt.h" +#include "renderer/web_engine_page_render_frame.h" +#include "content/public/renderer/render_frame.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" -#include "common/qt_messages.h" - -#include "content/public/renderer/render_view.h" #include "third_party/blink/public/web/web_document.h" #include "third_party/blink/public/web/web_element.h" #include "third_party/blink/public/web/web_frame.h" @@ -50,49 +50,45 @@ #include "third_party/blink/public/web/web_local_frame.h" #include "third_party/blink/public/web/web_view.h" -RenderViewObserverQt::RenderViewObserverQt( - content::RenderView* render_view) - : content::RenderViewObserver(render_view) +namespace QtWebEngineCore { + +WebEnginePageRenderFrame::WebEnginePageRenderFrame(content::RenderFrame *render_frame) + : content::RenderFrameObserver(render_frame), m_binding(this) { + render_frame->GetAssociatedInterfaceRegistry()->AddInterface( + base::BindRepeating(&WebEnginePageRenderFrame::BindReceiver, base::Unretained(this))); } -void RenderViewObserverQt::onFetchDocumentMarkup(quint64 requestId) +void WebEnginePageRenderFrame::BindReceiver( + mojo::PendingAssociatedReceiver<qtwebenginepage::mojom::WebEnginePageRenderFrame> receiver) { - blink::WebString markup; - if (render_view()->GetWebView()->MainFrame()->IsWebLocalFrame()) - markup = blink::WebFrameContentDumper::DumpAsMarkup( - static_cast<blink::WebLocalFrame*>(render_view()->GetWebView()->MainFrame())); - Send(new RenderViewObserverHostQt_DidFetchDocumentMarkup(routing_id(), requestId, markup.Utf16())); + m_binding.Bind(std::move(receiver)); } -void RenderViewObserverQt::onFetchDocumentInnerText(quint64 requestId) +void WebEnginePageRenderFrame::FetchDocumentMarkup(uint64_t requestId, + FetchDocumentMarkupCallback callback) { - blink::WebString text; - if (render_view()->GetWebView()->MainFrame()->IsWebLocalFrame()) - text = blink::WebFrameContentDumper::DumpWebViewAsText( - render_view()->GetWebView(), - std::numeric_limits<std::size_t>::max()); - Send(new RenderViewObserverHostQt_DidFetchDocumentInnerText(routing_id(), requestId, text.Utf16())); + blink::WebString markup = + blink::WebFrameContentDumper::DumpAsMarkup(render_frame()->GetWebFrame()); + std::move(callback).Run(requestId, markup.Utf8()); } -void RenderViewObserverQt::onSetBackgroundColor(quint32 color) +void WebEnginePageRenderFrame::FetchDocumentInnerText(uint64_t requestId, + FetchDocumentInnerTextCallback callback) { - render_view()->GetWebView()->SetBaseBackgroundColor(color); + blink::WebString text = blink::WebFrameContentDumper::DumpWebViewAsText( + render_frame()->GetWebFrame()->View(), std::numeric_limits<std::size_t>::max()); + std::move(callback).Run(requestId, text.Utf8()); } -void RenderViewObserverQt::OnDestruct() +void WebEnginePageRenderFrame::SetBackgroundColor(uint32_t color) { - delete this; + render_frame()->GetWebFrame()->View()->SetBaseBackgroundColorOverride(color); } -bool RenderViewObserverQt::OnMessageReceived(const IPC::Message& message) +void WebEnginePageRenderFrame::OnDestruct() { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(RenderViewObserverQt, message) - IPC_MESSAGE_HANDLER(RenderViewObserverQt_FetchDocumentMarkup, onFetchDocumentMarkup) - IPC_MESSAGE_HANDLER(RenderViewObserverQt_FetchDocumentInnerText, onFetchDocumentInnerText) - IPC_MESSAGE_HANDLER(RenderViewObserverQt_SetBackgroundColor, onSetBackgroundColor) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; + delete this; +} + } diff --git a/src/core/compositor/stream_video_node.h b/src/core/renderer/web_engine_page_render_frame.h index 9d937791f..3fb4657c5 100644 --- a/src/core/compositor/stream_video_node.h +++ b/src/core/renderer/web_engine_page_render_frame.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWebEngine module of the Qt Toolkit. @@ -36,53 +36,40 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#ifndef WEB_ENGINE_PAGE_RENDER_FRAME_H +#define WEB_ENGINE_PAGE_RENDER_FRAME_H -#ifndef STREAM_VIDEO_NODE_H -#define STREAM_VIDEO_NODE_H +#include "content/public/renderer/render_frame_observer.h" +#include "mojo/public/cpp/bindings/associated_receiver.h" +#include "qtwebengine/browser/qtwebenginepage.mojom.h" -#include <QtQuick/qsgmaterial.h> -#include <QtQuick/qsgnode.h> - -QT_FORWARD_DECLARE_CLASS(QSGTexture) +namespace content { +class RenderFrame; +} namespace QtWebEngineCore { -// These classes duplicate, QtQuick style, the logic of GLRenderer::DrawStreamVideoQuad. -// Their behavior should stay as close as possible to GLRenderer. - -enum TextureTarget { ExternalTarget, RectangleTarget }; - -class StreamVideoMaterial : public QSGMaterial +class WebEnginePageRenderFrame : private content::RenderFrameObserver, + public qtwebenginepage::mojom::WebEnginePageRenderFrame { public: - StreamVideoMaterial(QSGTexture *texture, TextureTarget target); + WebEnginePageRenderFrame(content::RenderFrame *render_frame); + WebEnginePageRenderFrame(const WebEnginePageRenderFrame &) = delete; + WebEnginePageRenderFrame &operator=(const WebEnginePageRenderFrame &) = delete; - QSGMaterialType *type() const override - { - static QSGMaterialType theType; - return &theType; - } - - QSGMaterialShader *createShader() const override; - - QSGTexture *m_texture; - QMatrix4x4 m_texMatrix; - TextureTarget m_target; -}; - -class StreamVideoNode : public QSGGeometryNode -{ -public: - StreamVideoNode(QSGTexture *texture, bool flip, TextureTarget target); - void setRect(const QRectF &rect); - void setTextureMatrix(const QMatrix4x4 &matrix); +private: + void FetchDocumentMarkup(uint64_t requestId, FetchDocumentMarkupCallback callback) override; + void FetchDocumentInnerText(uint64_t requestId, + FetchDocumentInnerTextCallback callback) override; + void SetBackgroundColor(uint32_t color) override; + void OnDestruct() override; + void + BindReceiver(mojo::PendingAssociatedReceiver<qtwebenginepage::mojom::WebEnginePageRenderFrame> + receiver); private: - QSGGeometry m_geometry; - bool m_flip; - StreamVideoMaterial *m_material; + mojo::AssociatedReceiver<qtwebenginepage::mojom::WebEnginePageRenderFrame> m_binding; }; - } // namespace -#endif // STREAM_VIDEO_NODE_H +#endif // WEB_ENGINE_PAGE_RENDER_FRAME_H diff --git a/src/core/renderer_host/pepper/pepper_flash_browser_host_qt.cpp b/src/core/renderer_host/pepper/pepper_flash_browser_host_qt.cpp index d54a9cdf2..8fa277e78 100644 --- a/src/core/renderer_host/pepper/pepper_flash_browser_host_qt.cpp +++ b/src/core/renderer_host/pepper/pepper_flash_browser_host_qt.cpp @@ -45,29 +45,22 @@ #include "pepper_flash_browser_host_qt.h" #include "base/time/time.h" -#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_ppapi_host.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/render_process_host.h" #include "ipc/ipc_message_macros.h" #include "ppapi/c/pp_errors.h" -#include "ppapi/c/private/ppb_flash.h" #include "ppapi/host/dispatch_host_message.h" #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/proxy/resource_message_params.h" #include "ppapi/shared_impl/time_conversion.h" #include "qtwebenginecoreglobal_p.h" -#include "url/gurl.h" #if defined(OS_WIN) #include <windows.h> -#elif defined(OS_MACOSX) +#elif defined(OS_MAC) #include <CoreServices/CoreServices.h> #endif using content::BrowserPpapiHost; -using content::BrowserThread; -using content::RenderProcessHost; namespace QtWebEngineCore { @@ -75,11 +68,8 @@ PepperFlashBrowserHostQt::PepperFlashBrowserHostQt(BrowserPpapiHost* host, PP_Instance instance, PP_Resource resource) : ResourceHost(host->GetPpapiHost(), instance, resource), - host_(host), weak_factory_(this) { - int unused; - host->GetRenderFrameIDsForInstance(instance, &render_process_id_, &unused); } PepperFlashBrowserHostQt::~PepperFlashBrowserHostQt() {} @@ -109,7 +99,7 @@ int32_t PepperFlashBrowserHostQt::OnUpdateActivity(ppapi::host::HostMessageConte int value = 0; if (SystemParametersInfo(SPI_GETSCREENSAVETIMEOUT, 0, &value, 0)) SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT, value, NULL, 0); -#elif defined(OS_MACOSX) +#elif defined(OS_MAC) UpdateSystemActivity(OverallAct); #endif return PP_OK; diff --git a/src/core/renderer_host/pepper/pepper_flash_browser_host_qt.h b/src/core/renderer_host/pepper/pepper_flash_browser_host_qt.h index 5d1107dfb..d6d2c8656 100644 --- a/src/core/renderer_host/pepper/pepper_flash_browser_host_qt.h +++ b/src/core/renderer_host/pepper/pepper_flash_browser_host_qt.h @@ -40,7 +40,6 @@ #ifndef PEPPER_FLASH_BROWSER_HOST_QT_H #define PEPPER_FLASH_BROWSER_HOST_QT_H -#include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "ppapi/host/host_message_context.h" #include "ppapi/host/resource_host.h" @@ -51,7 +50,6 @@ class Time; namespace content { class BrowserPpapiHost; -class ResourceContext; } class GURL; @@ -77,12 +75,6 @@ private: const base::Time& t); int32_t OnGetLocalDataRestrictions(ppapi::host::HostMessageContext* context); - void GetLocalDataRestrictions(ppapi::host::ReplyMessageContext reply_context, - const GURL& document_url, - const GURL& plugin_url); - - content::BrowserPpapiHost* host_; - int render_process_id_; base::WeakPtrFactory<PepperFlashBrowserHostQt> weak_factory_; DISALLOW_COPY_AND_ASSIGN(PepperFlashBrowserHostQt); diff --git a/src/core/renderer_host/pepper/pepper_isolated_file_system_message_filter.cpp b/src/core/renderer_host/pepper/pepper_isolated_file_system_message_filter.cpp index 5d7c3973f..f61c06ea9 100644 --- a/src/core/renderer_host/pepper/pepper_isolated_file_system_message_filter.cpp +++ b/src/core/renderer_host/pepper/pepper_isolated_file_system_message_filter.cpp @@ -58,7 +58,7 @@ #include "ppapi/host/ppapi_host.h" #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/shared_impl/file_system_util.h" -#include "storage/browser/fileapi/isolated_context.h" +#include "storage/browser/file_system/isolated_context.h" namespace QtWebEngineCore { @@ -81,11 +81,11 @@ PepperIsolatedFileSystemMessageFilter::PepperIsolatedFileSystemMessageFilter(int PepperIsolatedFileSystemMessageFilter::~PepperIsolatedFileSystemMessageFilter() {} -scoped_refptr<base::TaskRunner> PepperIsolatedFileSystemMessageFilter::OverrideTaskRunnerForMessage(const IPC::Message &) +scoped_refptr<base::SequencedTaskRunner> PepperIsolatedFileSystemMessageFilter::OverrideTaskRunnerForMessage(const IPC::Message &) { // In order to reach ExtensionSystem, we need to get ProfileManager first. // ProfileManager lives in UI thread, so we need to do this in UI thread. - return base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::UI}); + return base::CreateSingleThreadTaskRunner({content::BrowserThread::UI}); } int32_t PepperIsolatedFileSystemMessageFilter::OnResourceMessageReceived(const IPC::Message& msg, ppapi::host::HostMessageContext *context) diff --git a/src/core/renderer_host/pepper/pepper_isolated_file_system_message_filter.h b/src/core/renderer_host/pepper/pepper_isolated_file_system_message_filter.h index 750f7cea0..27c23d8e0 100644 --- a/src/core/renderer_host/pepper/pepper_isolated_file_system_message_filter.h +++ b/src/core/renderer_host/pepper/pepper_isolated_file_system_message_filter.h @@ -64,7 +64,7 @@ public: static PepperIsolatedFileSystemMessageFilter *Create(PP_Instance instance, content::BrowserPpapiHost *host); // ppapi::host::ResourceMessageFilter implementation. - scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(const IPC::Message &msg) override; + scoped_refptr<base::SequencedTaskRunner> OverrideTaskRunnerForMessage(const IPC::Message &msg) override; int32_t OnResourceMessageReceived(const IPC::Message &msg, ppapi::host::HostMessageContext *context) override; private: diff --git a/src/core/renderer_host/resource_dispatcher_host_delegate_qt.cpp b/src/core/renderer_host/resource_dispatcher_host_delegate_qt.cpp deleted file mode 100644 index a08e2cf88..000000000 --- a/src/core/renderer_host/resource_dispatcher_host_delegate_qt.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE.Chromium file. - -#include "resource_dispatcher_host_delegate_qt.h" - -#include "base/bind.h" -#include "base/guid.h" -#include "base/strings/stringprintf.h" -#include "base/task/post_task.h" -#include "content/public/browser/browser_context.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/download_manager.h" -#include "content/public/browser/download_request_utils.h" -#include "content/public/browser/navigation_controller.h" - -#include "content/public/browser/render_frame_host.h" -#include "content/public/browser/render_view_host.h" -#include "content/public/browser/resource_dispatcher_host.h" -#include "content/public/browser/resource_request_info.h" -#include "content/public/browser/stream_info.h" -#include "content/public/browser/web_contents.h" - -#include "extensions/extension_system_qt.h" -#include "extensions/browser/info_map.h" -#include "extensions/common/constants.h" -#include "extensions/common/extension.h" -#include "extensions/common/manifest_handlers/mime_types_handler.h" - -#include "net/base/escape.h" -#include "net/url_request/url_request.h" - -#include "profile_io_data_qt.h" -#include "type_conversion.h" -#include "web_contents_delegate_qt.h" -#include "web_engine_settings.h" - -namespace QtWebEngineCore { - -void OnPdfStreamIntercepted( - const GURL& original_url, - std::string extension_id, - int frame_tree_node_id, - const content::ResourceRequestInfo::WebContentsGetter& - web_contents_getter) { - content::WebContents* web_contents = web_contents_getter.Run(); - if (!web_contents) - return; - - WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt*>(web_contents->GetDelegate()); - if (!contentsDelegate) - return; - - WebEngineSettings *settings = contentsDelegate->webEngineSettings(); - if (!settings->testAttribute(WebEngineSettings::PdfViewerEnabled) - || !settings->testAttribute(WebEngineSettings::PluginsEnabled)) { - // If the applications has been set up to always download PDF files to open them in an - // external viewer, trigger the download. - std::unique_ptr<download::DownloadUrlParameters> params( - content::DownloadRequestUtils::CreateDownloadForWebContentsMainFrame( - web_contents, original_url, MISSING_TRAFFIC_ANNOTATION)); - content::BrowserContext::GetDownloadManager(web_contents->GetBrowserContext()) - ->DownloadUrl(std::move(params)); - return; - } - - // The URL passes the original pdf resource url, that will be requested - // by the pdf viewer extension page. - content::NavigationController::LoadURLParams params( - GURL(base::StringPrintf("%s://%s/index.html?%s", extensions::kExtensionScheme, - extension_id.c_str(), - original_url.spec().c_str()))); - - params.frame_tree_node_id = frame_tree_node_id; - web_contents->GetController().LoadURLWithParams(params); -} - -bool ResourceDispatcherHostDelegateQt::ShouldInterceptResourceAsStream(net::URLRequest *request, - const std::string &mime_type, - GURL *origin, - std::string *payload) -{ - content::ResourceRequestInfo* info = - content::ResourceRequestInfo::ForRequest(request); - - int render_process_host_id = -1; - int render_frame_id = -1; - if (!content::ResourceRequestInfo::GetRenderFrameForRequest(request, &render_process_host_id, &render_frame_id)) - return false; - - std::vector<std::string> whitelist = MimeTypesHandler::GetMIMETypeWhitelist(); - - extensions::ExtensionSystemQt *extensionSystem = ProfileIODataQt::FromResourceContext(info->GetContext())->GetExtensionSystem(); - if (!extensionSystem) - return false; - - const scoped_refptr<const extensions::InfoMap> extension_info_map(extensionSystem->info_map()); - - for (const std::string &extension_id : whitelist) { - const extensions::Extension *extension = extension_info_map->extensions().GetByID(extension_id); - if (!extension) - continue; - - MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension); - if (!handler) - continue; - if (handler->CanHandleMIMEType(mime_type)) { - StreamTargetInfo target_info; - *origin = extensions::Extension::GetBaseURLFromExtensionId(extension_id); - target_info.extension_id = extension_id; - target_info.view_id = base::GenerateGUID(); - *payload = target_info.view_id; - stream_target_info_[request] = target_info; - return true; - } - } - return false; -} - -// Informs the delegate that a Stream was created. The Stream can be read from -// the blob URL of the Stream, but can only be read once. -void ResourceDispatcherHostDelegateQt::OnStreamCreated(net::URLRequest *request, - std::unique_ptr<content::StreamInfo> stream) -{ - content::ResourceRequestInfo *info = content::ResourceRequestInfo::ForRequest(request); - std::map<net::URLRequest *, StreamTargetInfo>::iterator ix = stream_target_info_.find(request); - CHECK(ix != stream_target_info_.end()); - int render_frame_id = -1; - int render_process_id = -1; - if (!content::ResourceRequestInfo::GetRenderFrameForRequest(request, &render_process_id, &render_frame_id)) { - stream_target_info_.erase(request); - request->Cancel(); - return; - } - - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&OnPdfStreamIntercepted, - request->url(), ix->second.extension_id, - info->GetFrameTreeNodeId(), info->GetWebContentsGetterForRequest() - ) - ); - stream_target_info_.erase(request); -} - -} // namespace QtWebEngineCore diff --git a/src/core/renderer_host/user_resource_controller_host.cpp b/src/core/renderer_host/user_resource_controller_host.cpp index ed4d736f2..cea246c37 100644 --- a/src/core/renderer_host/user_resource_controller_host.cpp +++ b/src/core/renderer_host/user_resource_controller_host.cpp @@ -48,45 +48,55 @@ #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" +#include "qtwebengine/userscript/userscript.mojom.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" namespace QtWebEngineCore { -class UserResourceControllerHost::WebContentsObserverHelper : public content::WebContentsObserver { +class UserResourceControllerHost::WebContentsObserverHelper : public content::WebContentsObserver +{ public: WebContentsObserverHelper(UserResourceControllerHost *, content::WebContents *); // WebContentsObserver overrides: void RenderFrameCreated(content::RenderFrameHost *renderFrameHost) override; - void RenderFrameHostChanged(content::RenderFrameHost *oldHost, - content::RenderFrameHost *newHost) override; + void RenderFrameHostChanged(content::RenderFrameHost *oldHost, content::RenderFrameHost *newHost) override; + void RenderFrameDeleted(content::RenderFrameHost *render_frame_host) override; void WebContentsDestroyed() override; private: UserResourceControllerHost *m_controllerHost; }; -UserResourceControllerHost::WebContentsObserverHelper::WebContentsObserverHelper(UserResourceControllerHost *controller, content::WebContents *contents) - : content::WebContentsObserver(contents) - , m_controllerHost(controller) +UserResourceControllerHost::WebContentsObserverHelper::WebContentsObserverHelper(UserResourceControllerHost *controller, + content::WebContents *contents) + : content::WebContentsObserver(contents) + , m_controllerHost(controller) { } -void UserResourceControllerHost::WebContentsObserverHelper::RenderFrameCreated( - content::RenderFrameHost *renderFrameHost) +void UserResourceControllerHost::WebContentsObserverHelper::RenderFrameCreated(content::RenderFrameHost *renderFrameHost) { content::WebContents *contents = web_contents(); + auto &remote = m_controllerHost->GetUserResourceControllerRenderFrame(renderFrameHost); const QList<UserScript> scripts = m_controllerHost->m_perContentsScripts.value(contents); for (const UserScript &script : scripts) - renderFrameHost->Send(new RenderFrameObserverHelper_AddScript( - renderFrameHost->GetRoutingID(), script.data())); + remote->AddScript(script.data()); } -void UserResourceControllerHost::WebContentsObserverHelper::RenderFrameHostChanged( - content::RenderFrameHost *oldHost, - content::RenderFrameHost *newHost) +void UserResourceControllerHost::WebContentsObserverHelper::RenderFrameHostChanged(content::RenderFrameHost *oldHost, + content::RenderFrameHost *newHost) { - if (oldHost) - oldHost->Send(new RenderFrameObserverHelper_ClearScripts(oldHost->GetRoutingID())); + if (oldHost) { + auto &remote = m_controllerHost->GetUserResourceControllerRenderFrame(oldHost); + remote->ClearScripts(); + } +} + +void UserResourceControllerHost::WebContentsObserverHelper::RenderFrameDeleted( + content::RenderFrameHost *render_frame_host) +{ + m_controllerHost->m_renderFrames.erase(render_frame_host); } void UserResourceControllerHost::WebContentsObserverHelper::WebContentsDestroyed() @@ -95,10 +105,12 @@ void UserResourceControllerHost::WebContentsObserverHelper::WebContentsDestroyed delete this; } -class UserResourceControllerHost::RenderProcessObserverHelper : public content::RenderProcessHostObserver { +class UserResourceControllerHost::RenderProcessObserverHelper : public content::RenderProcessHostObserver +{ public: RenderProcessObserverHelper(UserResourceControllerHost *); void RenderProcessHostDestroyed(content::RenderProcessHost *) override; + private: UserResourceControllerHost *m_controllerHost; }; @@ -111,6 +123,7 @@ UserResourceControllerHost::RenderProcessObserverHelper::RenderProcessObserverHe void UserResourceControllerHost::RenderProcessObserverHelper::RenderProcessHostDestroyed(content::RenderProcessHost *renderer) { Q_ASSERT(m_controllerHost); + delete m_controllerHost->m_observedProcesses[renderer]; m_controllerHost->m_observedProcesses.remove(renderer); } @@ -123,8 +136,8 @@ void UserResourceControllerHost::addUserScript(const UserScript &script, WebCont if (isProfileWideScript) { if (!m_profileWideScripts.contains(script)) { m_profileWideScripts.append(script); - for (content::RenderProcessHost *renderer : qAsConst(m_observedProcesses)) - renderer->Send(new UserResourceController_AddScript(script.data())); + for (auto controller : m_observedProcesses.values()) + (*controller)->AddScript(script.data()); } } else { content::WebContents *contents = adapter->webContents(); @@ -141,36 +154,22 @@ void UserResourceControllerHost::addUserScript(const UserScript &script, WebCont m_perContentsScripts.insert(contents, currentScripts); } } - contents->GetRenderViewHost()->Send( - new RenderFrameObserverHelper_AddScript( - contents->GetRenderViewHost()->GetMainFrame()->GetRoutingID(), - script.data())); + GetUserResourceControllerRenderFrame(contents->GetRenderViewHost()->GetMainFrame()) + ->AddScript(script.data()); } } -bool UserResourceControllerHost::containsUserScript(const UserScript &script, WebContentsAdapter *adapter) -{ - if (script.isNull()) - return false; - // Global scripts should be dispatched to all our render processes. - const bool isProfileWideScript = !adapter; - if (isProfileWideScript) - return m_profileWideScripts.contains(script); - return m_perContentsScripts.value(adapter->webContents()).contains(script); -} - bool UserResourceControllerHost::removeUserScript(const UserScript &script, WebContentsAdapter *adapter) { if (script.isNull()) return false; const bool isProfileWideScript = !adapter; if (isProfileWideScript) { - QList<UserScript>::iterator it - = std::find(m_profileWideScripts.begin(), m_profileWideScripts.end(), script); + QList<UserScript>::iterator it = std::find(m_profileWideScripts.begin(), m_profileWideScripts.end(), script); if (it == m_profileWideScripts.end()) return false; - for (content::RenderProcessHost *renderer : qAsConst(m_observedProcesses)) - renderer->Send(new UserResourceController_RemoveScript((*it).data())); + for (auto controller : m_observedProcesses.values()) + (*controller)->RemoveScript((*it).data()); m_profileWideScripts.erase(it); } else { content::WebContents *contents = adapter->webContents(); @@ -180,10 +179,8 @@ bool UserResourceControllerHost::removeUserScript(const UserScript &script, WebC QList<UserScript>::iterator it = std::find(list.begin(), list.end(), script); if (it == list.end()) return false; - contents->GetRenderViewHost()->Send( - new RenderFrameObserverHelper_RemoveScript( - contents->GetMainFrame()->GetRoutingID(), - (*it).data())); + GetUserResourceControllerRenderFrame(contents->GetRenderViewHost()->GetMainFrame()) + ->RemoveScript((*it).data()); list.erase(it); } return true; @@ -194,24 +191,18 @@ void UserResourceControllerHost::clearAllScripts(WebContentsAdapter *adapter) const bool isProfileWideScript = !adapter; if (isProfileWideScript) { m_profileWideScripts.clear(); - for (content::RenderProcessHost *renderer : qAsConst(m_observedProcesses)) - renderer->Send(new UserResourceController_ClearScripts); + for (auto controller : m_observedProcesses.values()) + (*controller)->ClearScripts(); } else { content::WebContents *contents = adapter->webContents(); m_perContentsScripts.remove(contents); - contents->GetRenderViewHost()->Send( - new RenderFrameObserverHelper_ClearScripts(contents->GetMainFrame()->GetRoutingID())); + mojo::AssociatedRemote<qtwebengine::mojom::UserResourceControllerRenderFrame> + userResourceController; + GetUserResourceControllerRenderFrame(contents->GetRenderViewHost()->GetMainFrame()) + ->ClearScripts(); } } -const QList<UserScript> UserResourceControllerHost::registeredScripts(WebContentsAdapter *adapter) const -{ - const bool isProfileWideScript = !adapter; - if (isProfileWideScript) - return m_profileWideScripts; - return m_perContentsScripts.value(adapter->webContents()); -} - void UserResourceControllerHost::reserve(WebContentsAdapter *adapter, int count) { const bool isProfileWideScript = !adapter; @@ -223,15 +214,18 @@ void UserResourceControllerHost::reserve(WebContentsAdapter *adapter, int count) void UserResourceControllerHost::renderProcessStartedWithHost(content::RenderProcessHost *renderer) { - if (m_observedProcesses.contains(renderer)) + if (m_observedProcesses.keys().contains(renderer)) return; if (m_renderProcessObserver.isNull()) m_renderProcessObserver.reset(new RenderProcessObserverHelper(this)); renderer->AddObserver(m_renderProcessObserver.data()); - m_observedProcesses.insert(renderer); - for (const UserScript &script : qAsConst(m_profileWideScripts)) - renderer->Send(new UserResourceController_AddScript(script.data())); + auto userResourceController = new UserResourceControllerRemote; + renderer->GetChannel()->GetRemoteAssociatedInterface(userResourceController); + m_observedProcesses.insert(renderer, userResourceController); + for (const UserScript &script : qAsConst(m_profileWideScripts)) { + (*userResourceController)->AddScript(script.data()); + } } void UserResourceControllerHost::webContentsDestroyed(content::WebContents *contents) @@ -245,8 +239,26 @@ UserResourceControllerHost::UserResourceControllerHost() UserResourceControllerHost::~UserResourceControllerHost() { - for (content::RenderProcessHost *renderer : qAsConst(m_observedProcesses)) + for (content::RenderProcessHost *renderer : m_observedProcesses.keys()) { renderer->RemoveObserver(m_renderProcessObserver.data()); + delete m_observedProcesses[renderer]; + } +} + +const UserResourceControllerRenderFrameRemote & +UserResourceControllerHost::GetUserResourceControllerRenderFrame(content::RenderFrameHost *rfh) +{ + auto it = m_renderFrames.find(rfh); + if (it == m_renderFrames.end()) { + UserResourceControllerRenderFrameRemote remote; + rfh->GetRemoteAssociatedInterfaces()->GetInterface(remote.BindNewEndpointAndPassReceiver()); + it = m_renderFrames.insert(std::make_pair(rfh, std::move(remote))).first; + } else if (it->second.is_bound() && !it->second.is_connected()) { + it->second.reset(); + rfh->GetRemoteAssociatedInterfaces()->GetInterface(&it->second); + } + + return it->second; } } // namespace diff --git a/src/core/renderer_host/user_resource_controller_host.h b/src/core/renderer_host/user_resource_controller_host.h index 16a73f5fb..8b6099dcf 100644 --- a/src/core/renderer_host/user_resource_controller_host.h +++ b/src/core/renderer_host/user_resource_controller_host.h @@ -53,31 +53,46 @@ #include "qtwebenginecoreglobal_p.h" -#include <QtCore/QSet> +#include <QtCore/QHash> #include <QtCore/QScopedPointer> +#include <map> #include "user_script.h" namespace content { class RenderProcessHost; class WebContents; +class RenderFrameHost; +} + +namespace mojo { +template <typename Type> +class AssociatedRemote; +} + +namespace qtwebengine { +namespace mojom { +class UserResourceController; +class UserResourceControllerRenderFrame; +} } namespace QtWebEngineCore { +using UserResourceControllerRemote = mojo::AssociatedRemote<qtwebengine::mojom::UserResourceController>; +using UserResourceControllerRenderFrameRemote = mojo::AssociatedRemote<qtwebengine::mojom::UserResourceControllerRenderFrame>; class WebContentsAdapter; -class Q_WEBENGINECORE_PRIVATE_EXPORT UserResourceControllerHost { +class Q_WEBENGINECORE_PRIVATE_EXPORT UserResourceControllerHost +{ public: UserResourceControllerHost(); ~UserResourceControllerHost(); void addUserScript(const UserScript &script, WebContentsAdapter *adapter); - bool containsUserScript(const UserScript &script, WebContentsAdapter *adapter); bool removeUserScript(const UserScript &script, WebContentsAdapter *adapter); void clearAllScripts(WebContentsAdapter *adapter); void reserve(WebContentsAdapter *adapter, int count); - const QList<UserScript> registeredScripts(WebContentsAdapter *adapter) const; void renderProcessStartedWithHost(content::RenderProcessHost *renderer); @@ -87,12 +102,15 @@ private: class RenderProcessObserverHelper; void webContentsDestroyed(content::WebContents *); + const UserResourceControllerRenderFrameRemote & + GetUserResourceControllerRenderFrame(content::RenderFrameHost *rfh); QList<UserScript> m_profileWideScripts; typedef QHash<content::WebContents *, QList<UserScript>> ContentsScriptsMap; ContentsScriptsMap m_perContentsScripts; - QSet<content::RenderProcessHost *> m_observedProcesses; + QHash<content::RenderProcessHost *, UserResourceControllerRemote *> m_observedProcesses; QScopedPointer<RenderProcessObserverHelper> m_renderProcessObserver; + std::map<content::RenderFrameHost *, UserResourceControllerRenderFrameRemote> m_renderFrames; }; } // namespace diff --git a/src/core/renderer_host/web_channel_ipc_transport_host.cpp b/src/core/renderer_host/web_channel_ipc_transport_host.cpp index 4547b7fcf..087e0e83b 100644 --- a/src/core/renderer_host/web_channel_ipc_transport_host.cpp +++ b/src/core/renderer_host/web_channel_ipc_transport_host.cpp @@ -61,7 +61,7 @@ inline QDebug operator<<(QDebug stream, content::RenderFrameHost *frame) return stream << "frame " << frame->GetRoutingID() << " in process " << frame->GetProcess()->GetID(); } -template <class T> +template<class T> inline QDebug operator<<(QDebug stream, const base::Optional<T> &opt) { if (opt) @@ -74,7 +74,7 @@ WebChannelIPCTransportHost::WebChannelIPCTransportHost(content::WebContents *con : QWebChannelAbstractTransport(parent) , content::WebContentsObserver(contents) , m_worldId(worldId) - , m_binding(contents, this) + , m_receiver(contents, this) { for (content::RenderFrameHost *frame : contents->GetAllFrames()) setWorldId(frame, worldId); @@ -96,10 +96,9 @@ void WebChannelIPCTransportHost::sendMessage(const QJsonObject &message) int size = 0; const char *rawData = doc.rawData(&size); content::RenderFrameHost *frame = web_contents()->GetMainFrame(); - qtwebchannel::mojom::WebChannelTransportRenderAssociatedPtr webChannelTransport; - frame->GetRemoteAssociatedInterfaces()->GetInterface(&webChannelTransport); qCDebug(log).nospace() << "sending webchannel message to " << frame << ": " << doc; - webChannelTransport->DispatchWebChannelMessage(std::vector<uint8_t>(rawData, rawData + size), m_worldId); + GetWebChannelIPCTransportRemote(frame)->DispatchWebChannelMessage( + std::vector<uint8_t>(rawData, rawData + size), m_worldId); } void WebChannelIPCTransportHost::setWorldId(uint32_t worldId) @@ -116,9 +115,7 @@ void WebChannelIPCTransportHost::setWorldId(content::RenderFrameHost *frame, uin if (!frame->IsRenderFrameLive()) return; qCDebug(log).nospace() << "sending setWorldId(" << worldId << ") message to " << frame; - qtwebchannel::mojom::WebChannelTransportRenderAssociatedPtr webChannelTransport; - frame->GetRemoteAssociatedInterfaces()->GetInterface(&webChannelTransport); - webChannelTransport->SetWorldId(worldId); + GetWebChannelIPCTransportRemote(frame)->SetWorldId(worldId); } void WebChannelIPCTransportHost::resetWorldId() @@ -126,9 +123,7 @@ void WebChannelIPCTransportHost::resetWorldId() for (content::RenderFrameHost *frame : web_contents()->GetAllFrames()) { if (!frame->IsRenderFrameLive()) return; - qtwebchannel::mojom::WebChannelTransportRenderAssociatedPtr webChannelTransport; - frame->GetRemoteAssociatedInterfaces()->GetInterface(&webChannelTransport); - webChannelTransport->ResetWorldId(); + GetWebChannelIPCTransportRemote(frame)->ResetWorldId(); } } @@ -136,12 +131,11 @@ void WebChannelIPCTransportHost::DispatchWebChannelMessage(const std::vector<uin { content::RenderFrameHost *frame = web_contents()->GetMainFrame(); - if (m_binding.GetCurrentTargetFrame() != frame) { + if (m_receiver.GetCurrentTargetFrame() != frame) { return; } - QJsonDocument doc = QJsonDocument::fromRawData( - reinterpret_cast<const char *>(binaryJson.data()), binaryJson.size()); + QJsonDocument doc = QJsonDocument::fromRawData(reinterpret_cast<const char *>(binaryJson.data()), binaryJson.size()); if (!doc.isObject()) { qCCritical(log).nospace() << "received invalid webchannel message from " << frame; @@ -157,4 +151,25 @@ void WebChannelIPCTransportHost::RenderFrameCreated(content::RenderFrameHost *fr setWorldId(frame, m_worldId); } +void WebChannelIPCTransportHost::RenderFrameDeleted(content::RenderFrameHost *rfh) +{ + m_renderFrames.erase(rfh); +} + +const mojo::AssociatedRemote<qtwebchannel::mojom::WebChannelTransportRender> & +WebChannelIPCTransportHost::GetWebChannelIPCTransportRemote(content::RenderFrameHost *rfh) +{ + auto it = m_renderFrames.find(rfh); + if (it == m_renderFrames.end()) { + mojo::AssociatedRemote<qtwebchannel::mojom::WebChannelTransportRender> remote; + rfh->GetRemoteAssociatedInterfaces()->GetInterface(remote.BindNewEndpointAndPassReceiver()); + it = m_renderFrames.insert(std::make_pair(rfh, std::move(remote))).first; + } else if (it->second.is_bound() && !it->second.is_connected()) { + it->second.reset(); + rfh->GetRemoteAssociatedInterfaces()->GetInterface(&it->second); + } + + return it->second; +} + } // namespace QtWebEngineCore diff --git a/src/core/renderer_host/web_channel_ipc_transport_host.h b/src/core/renderer_host/web_channel_ipc_transport_host.h index 94891f25f..d06483ee6 100644 --- a/src/core/renderer_host/web_channel_ipc_transport_host.h +++ b/src/core/renderer_host/web_channel_ipc_transport_host.h @@ -43,19 +43,21 @@ #include "qtwebenginecoreglobal.h" #include "content/public/browser/web_contents_observer.h" -#include "services/service_manager/public/cpp/binder_registry.h" -#include "content/public/browser/web_contents_binding_set.h" +#include "content/public/browser/web_contents_receiver_set.h" #include "qtwebengine/browser/qtwebchannel.mojom.h" #include <QWebChannelAbstractTransport> +#include <map> QT_FORWARD_DECLARE_CLASS(QString) namespace QtWebEngineCore { -class WebChannelIPCTransportHost : public QWebChannelAbstractTransport +class WebChannelIPCTransportHost + : public QWebChannelAbstractTransport , private content::WebContentsObserver - , qtwebchannel::mojom::WebChannelTransportHost { + , qtwebchannel::mojom::WebChannelTransportHost +{ public: WebChannelIPCTransportHost(content::WebContents *webContents, uint32_t worldId = 0, QObject *parent = nullptr); ~WebChannelIPCTransportHost() override; @@ -71,8 +73,12 @@ private: void resetWorldId(); void onWebChannelMessage(const std::vector<char> &message); + const mojo::AssociatedRemote<qtwebchannel::mojom::WebChannelTransportRender> & + GetWebChannelIPCTransportRemote(content::RenderFrameHost *rfh); + // WebContentsObserver void RenderFrameCreated(content::RenderFrameHost *frame) override; + void RenderFrameDeleted(content::RenderFrameHost *render_frame_host) override; // qtwebchannel::mojom::WebChannelTransportHost void DispatchWebChannelMessage(const std::vector<uint8_t> &binaryJson) override; @@ -80,7 +86,10 @@ private: // Empty only during construction/destruction. Synchronized to all the // WebChannelIPCTransports/RenderFrames in the observed WebContents. uint32_t m_worldId; - content::WebContentsFrameBindingSet<qtwebchannel::mojom::WebChannelTransportHost> m_binding; + content::WebContentsFrameReceiverSet<qtwebchannel::mojom::WebChannelTransportHost> m_receiver; + std::map<content::RenderFrameHost *, + mojo::AssociatedRemote<qtwebchannel::mojom::WebChannelTransportRender>> + m_renderFrames; }; } // namespace diff --git a/src/core/renderer_host/render_view_observer_host_qt.cpp b/src/core/renderer_host/web_engine_page_host.cpp index c097e102d..36907ef5a 100644 --- a/src/core/renderer_host/render_view_observer_host_qt.cpp +++ b/src/core/renderer_host/web_engine_page_host.cpp @@ -37,60 +37,76 @@ ** ****************************************************************************/ -#include "render_view_observer_host_qt.h" +#include "web_engine_page_host.h" -#include "common/qt_messages.h" -#include "content/public/browser/render_view_host.h" +#include "qtwebengine/browser/qtwebenginepage.mojom.h" #include "content/public/browser/web_contents.h" #include "render_widget_host_view_qt.h" #include "type_conversion.h" #include "web_contents_adapter_client.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" namespace QtWebEngineCore { -RenderViewObserverHostQt::RenderViewObserverHostQt(content::WebContents *webContents, WebContentsAdapterClient *adapterClient) - : content::WebContentsObserver(webContents) - , m_adapterClient(adapterClient) +WebEnginePageHost::WebEnginePageHost(content::WebContents *webContents, + WebContentsAdapterClient *adapterClient) + : content::WebContentsObserver(webContents), m_adapterClient(adapterClient) { } -void RenderViewObserverHostQt::fetchDocumentMarkup(quint64 requestId) +void WebEnginePageHost::FetchDocumentMarkup(uint64_t requestId) { - web_contents()->GetRenderViewHost()->Send( - new RenderViewObserverQt_FetchDocumentMarkup( - web_contents()->GetRenderViewHost()->GetRoutingID(), requestId)); + auto &remote = GetWebEnginePageRenderFrame(web_contents()->GetMainFrame()); + remote->FetchDocumentMarkup( + requestId, + base::BindOnce(&WebEnginePageHost::OnDidFetchDocumentMarkup, base::Unretained(this))); } -void RenderViewObserverHostQt::fetchDocumentInnerText(quint64 requestId) +void WebEnginePageHost::FetchDocumentInnerText(uint64_t requestId) { - web_contents()->GetRenderViewHost()->Send( - new RenderViewObserverQt_FetchDocumentInnerText( - web_contents()->GetRenderViewHost()->GetRoutingID(), requestId)); + auto &remote = GetWebEnginePageRenderFrame(web_contents()->GetMainFrame()); + remote->FetchDocumentInnerText(requestId, + base::BindOnce(&WebEnginePageHost::OnDidFetchDocumentInnerText, + base::Unretained(this))); } -bool RenderViewObserverHostQt::OnMessageReceived(const IPC::Message& message) +void WebEnginePageHost::OnDidFetchDocumentMarkup(uint64_t requestId, const std::string &markup) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(RenderViewObserverHostQt, message) - IPC_MESSAGE_HANDLER(RenderViewObserverHostQt_DidFetchDocumentMarkup, - onDidFetchDocumentMarkup) - IPC_MESSAGE_HANDLER(RenderViewObserverHostQt_DidFetchDocumentInnerText, - onDidFetchDocumentInnerText) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; + m_adapterClient->didFetchDocumentMarkup(requestId, toQt(markup)); +} +void WebEnginePageHost::OnDidFetchDocumentInnerText(uint64_t requestId, + const std::string &innerText) +{ + m_adapterClient->didFetchDocumentInnerText(requestId, toQt(innerText)); } -void RenderViewObserverHostQt::onDidFetchDocumentMarkup(quint64 requestId, const base::string16& markup) +void WebEnginePageHost::RenderFrameDeleted(content::RenderFrameHost *render_frame) { - m_adapterClient->didFetchDocumentMarkup(requestId, toQt(markup)); + m_renderFrames.erase(render_frame); } -void RenderViewObserverHostQt::onDidFetchDocumentInnerText(quint64 requestId, const base::string16& innerText) +void WebEnginePageHost::SetBackgroundColor(uint32_t color) { - m_adapterClient->didFetchDocumentInnerText(requestId, toQt(innerText)); + auto &remote = GetWebEnginePageRenderFrame(web_contents()->GetMainFrame()); + remote->SetBackgroundColor(color); +} + +const WebEnginePageRenderFrameRemote & +WebEnginePageHost::GetWebEnginePageRenderFrame(content::RenderFrameHost *rfh) +{ + auto it = m_renderFrames.find(rfh); + if (it == m_renderFrames.end()) { + WebEnginePageRenderFrameRemote remote; + rfh->GetRemoteAssociatedInterfaces()->GetInterface(remote.BindNewEndpointAndPassReceiver()); + it = m_renderFrames.insert(std::make_pair(rfh, std::move(remote))).first; + } else if (it->second.is_bound() && !it->second.is_connected()) { + it->second.reset(); + rfh->GetRemoteAssociatedInterfaces()->GetInterface(&it->second); + } + + return it->second; } } // namespace QtWebEngineCore diff --git a/src/core/renderer_host/render_view_observer_host_qt.h b/src/core/renderer_host/web_engine_page_host.h index a08263e07..f305d22ea 100644 --- a/src/core/renderer_host/render_view_observer_host_qt.h +++ b/src/core/renderer_host/web_engine_page_host.h @@ -37,36 +37,54 @@ ** ****************************************************************************/ -#ifndef RENDER_VIEW_OBSERVER_HOST_QT_H -#define RENDER_VIEW_OBSERVER_HOST_QT_H +#ifndef WEB_ENGINE_PAGE_HOST_H +#define WEB_ENGINE_PAGE_HOST_H #include "content/public/browser/web_contents_observer.h" #include <QtGlobal> namespace content { - class WebContents; +class WebContents; +} + +namespace mojo { +template<typename Type> +class AssociatedRemote; +} + +namespace qtwebenginepage { +namespace mojom { +class WebEnginePageRenderFrame; +} } namespace QtWebEngineCore { +using WebEnginePageRenderFrameRemote = mojo::AssociatedRemote<qtwebenginepage::mojom::WebEnginePageRenderFrame>; + class WebContentsAdapterClient; -class RenderViewObserverHostQt : public content::WebContentsObserver +class WebEnginePageHost : public content::WebContentsObserver { public: - RenderViewObserverHostQt(content::WebContents*, WebContentsAdapterClient *adapterClient); - void fetchDocumentMarkup(quint64 requestId); - void fetchDocumentInnerText(quint64 requestId); + WebEnginePageHost(content::WebContents *, WebContentsAdapterClient *adapterClient); + void FetchDocumentMarkup(uint64_t requestId); + void FetchDocumentInnerText(uint64_t requestId); + void RenderFrameDeleted(content::RenderFrameHost *render_frame) override; + void SetBackgroundColor(uint32_t color); private: - bool OnMessageReceived(const IPC::Message& message) override; - void onDidFetchDocumentMarkup(quint64 requestId, const base::string16& markup); - void onDidFetchDocumentInnerText(quint64 requestId, const base::string16& innerText); + void OnDidFetchDocumentMarkup(uint64_t requestId, const std::string &markup); + void OnDidFetchDocumentInnerText(uint64_t requestId, const std::string &innerText); + const WebEnginePageRenderFrameRemote & + GetWebEnginePageRenderFrame(content::RenderFrameHost *rfh); +private: WebContentsAdapterClient *m_adapterClient; + std::map<content::RenderFrameHost *, WebEnginePageRenderFrameRemote> m_renderFrames; }; } // namespace QtWebEngineCore -#endif // RENDER_VIEW_OBSERVER_HOST_QT_H +#endif // WEB_ENGINE_PAGE_HOST_H diff --git a/src/core/resource_bundle_qt.cpp b/src/core/resource_bundle_qt.cpp index dc7507f34..4e814a806 100644 --- a/src/core/resource_bundle_qt.cpp +++ b/src/core/resource_bundle_qt.cpp @@ -38,9 +38,12 @@ ****************************************************************************/ #include "base/command_line.h" +#include "base/files/file_util.h" +#include "base/logging.h" #include "base/metrics/histogram_macros.h" +#include "base/notreached.h" #include "content/public/common/content_switches.h" -#include "services/service_manager/sandbox/switches.h" +#include "sandbox/policy/switches.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/data_pack.h" #include "ui/base/resource/resource_bundle.h" @@ -58,17 +61,15 @@ namespace ui { void ResourceBundle::LoadCommonResources() { // We repacked the resources we need and installed them. now let chromium mmap that file. - AddDataPackFromPath(WebEngineLibraryInfo::getPath(QT_RESOURCES_PAK), SCALE_FACTOR_NONE); AddDataPackFromPath(WebEngineLibraryInfo::getPath(QT_RESOURCES_100P_PAK), SCALE_FACTOR_100P); AddDataPackFromPath(WebEngineLibraryInfo::getPath(QT_RESOURCES_200P_PAK), SCALE_FACTOR_200P); + AddDataPackFromPath(WebEngineLibraryInfo::getPath(QT_RESOURCES_PAK), SCALE_FACTOR_NONE); AddOptionalDataPackFromPath(WebEngineLibraryInfo::getPath(QT_RESOURCES_DEVTOOLS_PAK), SCALE_FACTOR_NONE); } gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id) { - LOG(WARNING) << "Unable to load image with id " << resource_id; - NOTREACHED(); // Want to assert in debug mode. - return GetEmptyImage(); + return GetImageNamed(resource_id); } // static @@ -77,7 +78,7 @@ bool ResourceBundle::LocaleDataPakExists(const std::string& locale) #if defined(OS_LINUX) base::CommandLine *parsed_command_line = base::CommandLine::ForCurrentProcess(); std::string process_type = parsed_command_line->GetSwitchValueASCII(switches::kProcessType); - bool no_sandbox = parsed_command_line->HasSwitch(service_manager::switches::kNoSandbox); + bool no_sandbox = parsed_command_line->HasSwitch(sandbox::policy::switches::kNoSandbox); if (process_type == switches::kRendererProcess && !no_sandbox) { // The Renderer Process is sandboxed thus only one locale is available in it. // The particular one is passed by the --lang command line option. @@ -89,14 +90,15 @@ bool ResourceBundle::LocaleDataPakExists(const std::string& locale) } #endif - return !GetLocaleFilePath(locale, true).empty(); + const auto path = GetLocaleFilePath(locale); + return !path.empty() && base::PathExists(path); } -std::string ResourceBundle::LoadLocaleResources(const std::string& pref_locale) +std::string ResourceBundle::LoadLocaleResources(const std::string &pref_locale, bool /*crash_on_failure*/) { DCHECK(!locale_resources_data_.get()) << "locale.pak already loaded"; - std::string app_locale = l10n_util::GetApplicationLocale(pref_locale); + std::string app_locale = l10n_util::GetApplicationLocale(pref_locale, false /* set_icu_locale */); #if defined(OS_LINUX) int locale_fd = base::GlobalDescriptors::GetInstance()->MaybeGet(kWebEngineLocale); @@ -110,7 +112,7 @@ std::string ResourceBundle::LoadLocaleResources(const std::string& pref_locale) base::FilePath locale_file_path = GetOverriddenPakPath(); if (locale_file_path.empty()) - locale_file_path = GetLocaleFilePath(app_locale, true); + locale_file_path = GetLocaleFilePath(app_locale); if (locale_file_path.empty()) { // It's possible that there is no locale.pak. diff --git a/src/core/resource_context_qt.h b/src/core/resource_context_qt.h index 4107e7c24..efd3d2e7e 100644 --- a/src/core/resource_context_qt.h +++ b/src/core/resource_context_qt.h @@ -42,21 +42,6 @@ #include "content/public/browser/resource_context.h" -#include "extensions/buildflags/buildflags.h" - -namespace net { -class URLRequestContext; -class URLRequestContextGetter; -} - -#if BUILDFLAG(ENABLE_EXTENSIONS) -namespace extensions { -class ExtensionSystemQt; -} -#endif // BUILDFLAG(ENABLE_EXTENSIONS) - -class GURL; - namespace QtWebEngineCore { class ProfileIODataQt; diff --git a/src/core/service/service_qt.cpp b/src/core/service/service_qt.cpp deleted file mode 100644 index 83948e396..000000000 --- a/src/core/service/service_qt.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// based on chrome/browser/chrome_service.cc: -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "service_qt.h" - -#include "base/no_destructor.h" -#include "base/task/post_task.h" -#include "components/spellcheck/spellcheck_buildflags.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/content_browser_client.h" -#include "services/service_manager/public/cpp/binder_registry.h" -#include "services/service_manager/public/cpp/connector.h" -#include "services/service_manager/public/cpp/service.h" -#include "services/service_manager/public/cpp/service_binding.h" - -#if BUILDFLAG(ENABLE_SPELLCHECK) -#include "chrome/browser/spellchecker/spell_check_host_chrome_impl.h" -#endif - -class ServiceQt::IOThreadContext : public service_manager::Service { -public: - IOThreadContext(); - ~IOThreadContext() override = default; - - void BindServiceRequest(service_manager::mojom::ServiceRequest request); - void BindConnector(service_manager::mojom::ConnectorRequest connector_request); - -private: - void BindConnectorOnIOThread(service_manager::mojom::ConnectorRequest connector_request); - - // service_manager::Service: - void OnStart() override; - void OnBindInterface(const service_manager::BindSourceInfo &remote_info, - const std::string &name, - mojo::ScopedMessagePipeHandle handle) override; - - service_manager::mojom::ConnectorRequest m_connectorRequest; - service_manager::ServiceBinding m_serviceBinding{this}; - service_manager::BinderRegistry m_registry; - service_manager::BinderRegistryWithArgs<const service_manager::BindSourceInfo&> m_registry_with_source_info; - - DISALLOW_COPY_AND_ASSIGN(IOThreadContext); -}; - -ServiceQt::IOThreadContext::IOThreadContext() -{ -#if BUILDFLAG(ENABLE_SPELLCHECK) - scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner = - base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::UI}); - m_registry_with_source_info.AddInterface(base::BindRepeating(&SpellCheckHostChromeImpl::Create), ui_task_runner); -#endif -} - -void ServiceQt::IOThreadContext::BindServiceRequest(service_manager::mojom::ServiceRequest request) -{ - m_serviceBinding.Bind(std::move(request)); -} - -void ServiceQt::IOThreadContext::BindConnector(service_manager::mojom::ConnectorRequest connector_request) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - // NOTE: It's not safe to modify |connector_request_| here since it's read - // on the IO thread. Post a task instead. As long as this task is posted - // before any code attempts to connect to the chrome service, there's no - // race. - base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO})->PostTask( - FROM_HERE, - base::BindOnce(&IOThreadContext::BindConnectorOnIOThread, - base::Unretained(this), - std::move(connector_request))); -} - -void ServiceQt::IOThreadContext::BindConnectorOnIOThread(service_manager::mojom::ConnectorRequest connector_request) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - m_connectorRequest = std::move(connector_request); -} - -void ServiceQt::IOThreadContext::OnStart() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - DCHECK(m_connectorRequest.is_pending()); - m_serviceBinding.GetConnector()->BindConnectorRequest(std::move(m_connectorRequest)); -} - -void ServiceQt::IOThreadContext::OnBindInterface(const service_manager::BindSourceInfo &remote_info, - const std::string &name, - mojo::ScopedMessagePipeHandle handle) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - content::OverrideOnBindInterface(remote_info, name, &handle); - if (!handle.is_valid()) - return; - - if (!m_registry.TryBindInterface(name, &handle)) - m_registry_with_source_info.TryBindInterface(name, &handle, remote_info); -} - -ServiceQt *ServiceQt::GetInstance() -{ - static base::NoDestructor<ServiceQt> service; - return service.get(); -} - -content::ServiceManagerConnection::ServiceRequestHandler ServiceQt::CreateServiceQtRequestHandler() -{ - return base::BindRepeating(&ServiceQt::BindServiceQtRequest, base::Unretained(this)); -} - -ServiceQt::ServiceQt() : m_ioThreadContext(std::make_unique<IOThreadContext>()) -{} - -ServiceQt::~ServiceQt() = default; - -void ServiceQt::InitConnector() -{ - service_manager::mojom::ConnectorRequest request; - m_connector = service_manager::Connector::Create(&request); - m_ioThreadContext->BindConnector(std::move(request)); -} - -void ServiceQt::BindServiceQtRequest(service_manager::mojom::ServiceRequest request) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - m_ioThreadContext->BindServiceRequest(std::move(request)); -} diff --git a/src/core/touch_selection_controller_client_qt.cpp b/src/core/touch_selection_controller_client_qt.cpp index 0f44210d1..ef7b22ecc 100644 --- a/src/core/touch_selection_controller_client_qt.cpp +++ b/src/core/touch_selection_controller_client_qt.cpp @@ -45,7 +45,7 @@ #include "web_contents_adapter.h" #include "web_contents_adapter_client.h" -#include "content/browser/frame_host/render_frame_host_impl.h" +#include "content/browser/renderer_host/render_frame_host_impl.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "ui/gfx/geometry/size_conversions.h" @@ -229,29 +229,29 @@ void TouchSelectionControllerClientQt::SetNeedsAnimate() void TouchSelectionControllerClientQt::MoveCaret(const gfx::PointF& position) { - content::mojom::FrameInputHandler *frameInputHandler = m_rwhv->getFrameInputHandler(); - if (!frameInputHandler) + auto *frameWidgetInputHandler = m_rwhv->getFrameWidgetInputHandler(); + if (!frameWidgetInputHandler) return; - frameInputHandler->MoveCaret(gfx::ToRoundedPoint(position)); + frameWidgetInputHandler->MoveCaret(gfx::ToRoundedPoint(position)); } void TouchSelectionControllerClientQt::MoveRangeSelectionExtent(const gfx::PointF& extent) { - content::mojom::FrameInputHandler *frameInputHandler = m_rwhv->getFrameInputHandler(); - if (!frameInputHandler) + auto *frameWidgetInputHandler = m_rwhv->getFrameWidgetInputHandler(); + if (!frameWidgetInputHandler) return; - frameInputHandler->MoveRangeSelectionExtent(gfx::ToRoundedPoint(extent)); + frameWidgetInputHandler->MoveRangeSelectionExtent(gfx::ToRoundedPoint(extent)); } void TouchSelectionControllerClientQt::SelectBetweenCoordinates(const gfx::PointF& base, const gfx::PointF& extent) { - content::mojom::FrameInputHandler *frameInputHandler = m_rwhv->getFrameInputHandler(); - if (!frameInputHandler) + auto *frameWidgetInputHandler = m_rwhv->getFrameWidgetInputHandler(); + if (!frameWidgetInputHandler) return; - frameInputHandler->SelectRange(gfx::ToRoundedPoint(base), gfx::ToRoundedPoint(extent)); + frameWidgetInputHandler->SelectRange(gfx::ToRoundedPoint(base), gfx::ToRoundedPoint(extent)); } void TouchSelectionControllerClientQt::OnSelectionEvent(ui::SelectionEventType event) diff --git a/src/core/touch_selection_controller_client_qt.h b/src/core/touch_selection_controller_client_qt.h index 0d8dcf696..aadf72172 100644 --- a/src/core/touch_selection_controller_client_qt.h +++ b/src/core/touch_selection_controller_client_qt.h @@ -40,8 +40,8 @@ #ifndef TOUCH_SELECTION_CONTROLLER_CLIENT_QT_H #define TOUCH_SELECTION_CONTROLLER_CLIENT_QT_H +#include "content/public/browser/context_menu_params.h" #include "content/public/browser/touch_selection_controller_client_manager.h" -#include "content/public/common/context_menu_params.h" #include "ui/touch_selection/touch_selection_controller.h" #include "ui/touch_selection/touch_selection_menu_runner.h" diff --git a/src/core/type_conversion.cpp b/src/core/type_conversion.cpp index aea924dbd..3723f97ea 100644 --- a/src/core/type_conversion.cpp +++ b/src/core/type_conversion.cpp @@ -39,11 +39,11 @@ #include "type_conversion.h" -#include <content/public/common/favicon_url.h> #include <net/cert/x509_certificate.h> #include <net/cert/x509_util.h> #include <ui/events/event_constants.h> #include <ui/gfx/image/image_skia.h> +#include "third_party/blink/public/mojom/favicon/favicon_url.mojom.h" #include <QtCore/qcoreapplication.h> #include <QtGui/qmatrix4x4.h> @@ -59,6 +59,11 @@ QImage toQImage(const SkBitmap &bitmap) case kRGBA_F16_SkColorType: case kRGBA_F32_SkColorType: case kRGBA_F16Norm_SkColorType: + case kR8G8_unorm_SkColorType: + case kA16_float_SkColorType: + case kA16_unorm_SkColorType: + case kR16G16_float_SkColorType: + case kR16G16_unorm_SkColorType: qWarning("Unknown or unsupported skia image format"); break; case kAlpha_8_SkColorType: @@ -128,9 +133,39 @@ QImage toQImage(const SkBitmap &bitmap) break; } break; + case kBGR_101010x_SkColorType: + case kBGRA_1010102_SkColorType: + switch (bitmap.alphaType()) { + case kUnknown_SkAlphaType: + break; + case kUnpremul_SkAlphaType: + // not supported - treat as opaque + case kOpaque_SkAlphaType: + image = toQImage(bitmap, QImage::Format_BGR30); + break; + case kPremul_SkAlphaType: + image = toQImage(bitmap, QImage::Format_A2BGR30_Premultiplied); + break; + } + break; case kGray_8_SkColorType: image = toQImage(bitmap, QImage::Format_Grayscale8); break; + case kR16G16B16A16_unorm_SkColorType: + switch (bitmap.alphaType()) { + case kUnknown_SkAlphaType: + break; + case kUnpremul_SkAlphaType: + image = toQImage(bitmap, QImage::Format_RGBA64); + break; + case kOpaque_SkAlphaType: + image = toQImage(bitmap, QImage::Format_RGBX64); + break; + case kPremul_SkAlphaType: + image = toQImage(bitmap, QImage::Format_RGBA64_Premultiplied); + break; + } + break; } return image; } @@ -222,27 +257,27 @@ int flagsFromModifiers(Qt::KeyboardModifiers modifiers) return modifierFlags; } -FaviconInfo::FaviconTypeFlags toQt(content::FaviconURL::IconType type) +FaviconInfo::FaviconTypeFlags toQt(blink::mojom::FaviconIconType type) { switch (type) { - case content::FaviconURL::IconType::kFavicon: + case blink::mojom::FaviconIconType::kFavicon: return FaviconInfo::Favicon; - case content::FaviconURL::IconType::kTouchIcon: + case blink::mojom::FaviconIconType::kTouchIcon: return FaviconInfo::TouchIcon; - case content::FaviconURL::IconType::kTouchPrecomposedIcon: + case blink::mojom::FaviconIconType::kTouchPrecomposedIcon: return FaviconInfo::TouchPrecomposedIcon; - case content::FaviconURL::IconType::kInvalid: + case blink::mojom::FaviconIconType::kInvalid: return FaviconInfo::InvalidIcon; } Q_UNREACHABLE(); return FaviconInfo::InvalidIcon; } -FaviconInfo toFaviconInfo(const content::FaviconURL &favicon_url) +FaviconInfo toFaviconInfo(const blink::mojom::FaviconURLPtr &favicon_url) { FaviconInfo info; - info.url = toQt(favicon_url.icon_url); - info.type = toQt(favicon_url.icon_type); + info.url = toQt(favicon_url->icon_url); + info.type = toQt(favicon_url->icon_type); // TODO: Add support for rel sizes attribute (favicon_url.icon_sizes): // http://www.w3schools.com/tags/att_link_sizes.asp info.size = QSize(0, 0); diff --git a/src/core/type_conversion.h b/src/core/type_conversion.h index 2275ae82e..1152ed9a9 100644 --- a/src/core/type_conversion.h +++ b/src/core/type_conversion.h @@ -52,9 +52,9 @@ #include <base/strings/nullable_string16.h> #include "base/files/file_path.h" #include "base/time/time.h" -#include "content/public/common/file_chooser_file_info.h" #include "favicon_manager.h" #include "net/cookies/canonical_cookie.h" +#include "third_party/blink/public/mojom/favicon/favicon_url.mojom-forward.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkPixelRef.h" @@ -66,10 +66,6 @@ QT_FORWARD_DECLARE_CLASS(QMatrix4x4) QT_FORWARD_DECLARE_CLASS(QSslCertificate) -namespace content { -struct FaviconURL; -} - namespace gfx { class ImageSkiaRep; } @@ -89,6 +85,17 @@ inline QString toQt(const base::string16 &string) #endif } +inline QString toQt(const base::Optional<base::string16> &string) +{ + if (!string.has_value()) + return QString(); +#if defined(OS_WIN) + return QString::fromStdWString(string->data()); +#else + return QString::fromUtf16(string->data()); +#endif +} + inline QString toQString(const std::string &string) { return QString::fromStdString(string); @@ -119,6 +126,13 @@ inline base::NullableString16 toNullableString16(const QString &qString) return base::NullableString16(toString16(qString), qString.isNull()); } +inline base::Optional<base::string16> toOptionalString16(const QString &qString) +{ + if (qString.isNull()) + return base::nullopt; + return base::make_optional(toString16(qString)); +} + inline QUrl toQt(const GURL &url) { if (url.is_valid()) @@ -246,43 +260,6 @@ inline base::FilePath toFilePath(const QString &str) return base::FilePath(toFilePathString(str)); } -template <typename T> -inline T fileListingHelper(const QString &) -// Clang is still picky about this though it should be supported eventually. -// See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#941 -#ifndef Q_CC_CLANG -= delete; -#else -{ return T(); } -#endif - -template <> -inline content::FileChooserFileInfo fileListingHelper<content::FileChooserFileInfo>(const QString &file) -{ - content::FileChooserFileInfo choose_file; - base::FilePath fp(toFilePath(file)); - choose_file.file_path = fp; - choose_file.display_name = fp.BaseName().value(); - return choose_file; -} - -template <> -inline base::FilePath fileListingHelper<base::FilePath>(const QString &file) -{ - return base::FilePath(toFilePathString(file)); -} - - -template <typename T> -inline std::vector<T> toVector(const QStringList &fileList) -{ - std::vector<T> selectedFiles; - selectedFiles.reserve(fileList.size()); - for (const QString &file : fileList) - selectedFiles.push_back(fileListingHelper<T>(file)); - return selectedFiles; -} - int flagsFromModifiers(Qt::KeyboardModifiers modifiers); inline QStringList fromVector(const std::vector<base::string16> &vector) @@ -294,7 +271,7 @@ inline QStringList fromVector(const std::vector<base::string16> &vector) return result; } -FaviconInfo toFaviconInfo(const content::FaviconURL &); +FaviconInfo toFaviconInfo(const blink::mojom::FaviconURLPtr &favicon_url); QList<QSslCertificate> toCertificateChain(net::X509Certificate *certificate); diff --git a/src/core/user_notification_controller.cpp b/src/core/user_notification_controller.cpp index 50d12e8fd..f94605a55 100644 --- a/src/core/user_notification_controller.cpp +++ b/src/core/user_notification_controller.cpp @@ -43,6 +43,7 @@ #include "base/callback.h" #include "content/public/browser/notification_event_dispatcher.h" +#include "third_party/blink/public/mojom/notifications/notification.mojom-shared.h" #include "third_party/blink/public/common/notifications/notification_resources.h" #include "third_party/blink/public/common/notifications/platform_notification_data.h" #include "ui/message_center/public/cpp/notification_delegate.h" diff --git a/src/core/user_notification_controller.h b/src/core/user_notification_controller.h index bab85c7ec..f0d7e348f 100644 --- a/src/core/user_notification_controller.h +++ b/src/core/user_notification_controller.h @@ -44,7 +44,7 @@ #include <QtCore/QSharedPointer> #include <QtCore/QUrl> -#include <QtGui/QIcon> +#include <QtGui/QImage> class GURL; diff --git a/src/core/user_script.cpp b/src/core/user_script.cpp index bdd6524ca..f4daaf7c6 100644 --- a/src/core/user_script.cpp +++ b/src/core/user_script.cpp @@ -37,7 +37,7 @@ ** ****************************************************************************/ -#include "common/user_script_data.h" +#include "qtwebengine/userscript/user_script_data.h" #include "user_script.h" #include "type_conversion.h" @@ -178,8 +178,11 @@ bool UserScript::operator==(const UserScript &other) const void UserScript::initData() { - if (scriptData.isNull()) + static uint64_t idCount = 0; + if (scriptData.isNull()) { scriptData.reset(new UserScriptData); + scriptData->scriptId = idCount++; + } } bool UserScript::isNull() const @@ -194,6 +197,11 @@ UserScriptData &UserScript::data() const void UserScript::parseMetadataHeader() { + // Clear previous values + scriptData->globs.clear(); + scriptData->excludeGlobs.clear(); + scriptData->urlPatterns.clear(); + // Logic taken from Chromium (extensions/browser/user_script_loader.cc) // http://wiki.greasespot.net/Metadata_block const std::string &script_text = scriptData->source; @@ -223,13 +231,13 @@ void UserScript::parseMetadataHeader() if (line_end == std::string::npos) line_end = script_text.length() - 1; - line.set(script_text.data() + line_start, line_end - line_start); + line = base::StringPiece(script_text.data() + line_start, line_end - line_start); if (!in_metadata) { - if (line.starts_with(kUserScriptBegin)) + if (base::StartsWith(line, kUserScriptBegin)) in_metadata = true; } else { - if (line.starts_with(kUserScriptEnd)) + if (base::StartsWith(line, kUserScriptEnd)) break; std::string value; diff --git a/src/core/user_script.h b/src/core/user_script.h index 8f65f4b74..e06141259 100644 --- a/src/core/user_script.h +++ b/src/core/user_script.h @@ -57,10 +57,9 @@ #include <QtCore/QSharedData> #include <QtCore/QString> -struct UserScriptData; namespace QtWebEngineCore { - +struct UserScriptData; class UserResourceControllerHost; class Q_WEBENGINECORE_PRIVATE_EXPORT UserScript : public QSharedData { diff --git a/src/core/visited_links_manager_qt.cpp b/src/core/visited_links_manager_qt.cpp index d4885e8e8..37343cc39 100644 --- a/src/core/visited_links_manager_qt.cpp +++ b/src/core/visited_links_manager_qt.cpp @@ -45,12 +45,12 @@ #include <base/files/file_util.h> #include "components/visitedlink/browser/visitedlink_delegate.h" -#include "components/visitedlink/browser/visitedlink_master.h" +#include "components/visitedlink/browser/visitedlink_writer.h" namespace QtWebEngineCore { namespace { -class BasicUrlIterator : public visitedlink::VisitedLinkMaster::URLIterator { +class BasicUrlIterator : public visitedlink::VisitedLinkWriter::URLIterator { public: BasicUrlIterator(const QList<QUrl> &urls) : m_urls(urls) {} virtual const GURL& NextURL() { m_currentUrl = toGurl(m_urls.takeFirst()); return m_currentUrl; } @@ -76,18 +76,18 @@ public: void VisitedLinksManagerQt::deleteAllVisitedLinkData() { - m_visitedLinkMaster->DeleteAllURLs(); + m_visitedLinkWriter->DeleteAllURLs(); } void VisitedLinksManagerQt::deleteVisitedLinkDataForUrls(const QList<QUrl> &urlsToDelete) { BasicUrlIterator iterator(urlsToDelete); - m_visitedLinkMaster->DeleteURLs(&iterator); + m_visitedLinkWriter->DeleteURLs(&iterator); } bool VisitedLinksManagerQt::containsUrl(const QUrl &url) const { - return m_visitedLinkMaster->IsVisited(toGurl(url)); + return m_visitedLinkWriter->IsVisited(toGurl(url)); } static void ensureDirectoryExists(const base::FilePath &path) @@ -111,8 +111,8 @@ VisitedLinksManagerQt::VisitedLinksManagerQt(ProfileQt *profile, bool persistVis Q_ASSERT(profile); if (persistVisitedLinks) ensureDirectoryExists(profile->GetPath()); - m_visitedLinkMaster.reset(new visitedlink::VisitedLinkMaster(profile, m_delegate.data(), persistVisitedLinks)); - m_visitedLinkMaster->Init(); + m_visitedLinkWriter.reset(new visitedlink::VisitedLinkWriter(profile, m_delegate.data(), persistVisitedLinks)); + m_visitedLinkWriter->Init(); } VisitedLinksManagerQt::~VisitedLinksManagerQt() @@ -121,8 +121,8 @@ VisitedLinksManagerQt::~VisitedLinksManagerQt() void VisitedLinksManagerQt::addUrl(const GURL &urlToAdd) { - Q_ASSERT(m_visitedLinkMaster); - m_visitedLinkMaster->AddURL(urlToAdd); + Q_ASSERT(m_visitedLinkWriter); + m_visitedLinkWriter->AddURL(urlToAdd); } } // namespace QtWebEngineCore diff --git a/src/core/visited_links_manager_qt.h b/src/core/visited_links_manager_qt.h index ecac8f30f..c4e24ce1f 100644 --- a/src/core/visited_links_manager_qt.h +++ b/src/core/visited_links_manager_qt.h @@ -60,7 +60,7 @@ class QUrl; QT_END_NAMESPACE namespace visitedlink { -class VisitedLinkMaster; +class VisitedLinkWriter; } class GURL; @@ -85,7 +85,7 @@ private: void addUrl(const GURL &); friend class WebContentsDelegateQt; - QScopedPointer<visitedlink::VisitedLinkMaster> m_visitedLinkMaster; + QScopedPointer<visitedlink::VisitedLinkWriter> m_visitedLinkWriter; QScopedPointer<VisitedLinkDelegateQt> m_delegate; }; diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index 4cfcf6acd..cca31e144 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -53,7 +53,7 @@ #include "profile_adapter.h" #include "profile_qt.h" #include "qwebenginecallback_p.h" -#include "renderer_host/render_view_observer_host_qt.h" +#include "renderer_host/web_engine_page_host.h" #include "render_widget_host_view_qt.h" #include "type_conversion.h" #include "web_contents_view_qt.h" @@ -61,12 +61,16 @@ #include "web_engine_settings.h" #include "base/command_line.h" +#include "base/metrics/user_metrics.h" #include "base/run_loop.h" +#include "base/task/current_thread.h" #include "base/task/post_task.h" #include "base/task/sequence_manager/sequence_manager_impl.h" #include "base/task/sequence_manager/thread_controller_with_message_pump_impl.h" #include "base/values.h" +#include "chrome/browser/tab_contents/form_interaction_tab_helper.h" #include "content/browser/renderer_host/render_view_host_impl.h" +#include "content/browser/renderer_host/text_input_manager.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/child_process_security_policy.h" @@ -83,15 +87,17 @@ #include "content/public/common/page_state.h" #include "content/public/common/page_zoom.h" #include "content/public/common/url_constants.h" -#include "content/public/common/web_preferences.h" -#include "content/public/common/webrtc_ip_handling_policy.h" #include "extensions/buildflags/buildflags.h" -#include "third_party/blink/public/web/web_media_player_action.h" +#include "third_party/blink/public/common/page/page_zoom.h" +#include "third_party/blink/public/common/peerconnection/webrtc_ip_handling_policy.h" +#include "third_party/blink/public/common/web_preferences/web_preferences.h" +#include "third_party/blink/public/mojom/frame/media_player_action.mojom.h" #include "printing/buildflags/buildflags.h" #include "ui/base/clipboard/clipboard.h" #include "ui/base/clipboard/clipboard_constants.h" #include "ui/base/clipboard/custom_data_helper.h" #include "ui/gfx/font_render_params.h" +#include "qtwebengine/browser/qtwebenginepage.mojom.h" #if QT_CONFIG(webengine_webchannel) #include "renderer_host/web_channel_ipc_transport_host.h" @@ -237,9 +243,7 @@ static void callbackOnPdfSavingFinished(WebContentsAdapterClient *adapterClient, static std::unique_ptr<content::WebContents> createBlankWebContents(WebContentsAdapterClient *adapterClient, content::BrowserContext *browserContext) { - content::WebContents::CreateParams create_params(browserContext, NULL); - create_params.routing_id = MSG_ROUTING_NONE; - create_params.initial_size = gfx::Size(kTestWindowWidth, kTestWindowHeight); + content::WebContents::CreateParams create_params(browserContext, nullptr); create_params.initially_hidden = true; std::unique_ptr<content::WebContents> webContents = content::WebContents::Create(create_params); @@ -370,6 +374,25 @@ static void deserializeNavigationHistory(QDataStream &input, int *currentIndex, } namespace { + +void Navigate(WebContentsAdapter *adapter, const content::NavigationController::LoadURLParams ¶ms) +{ + Q_ASSERT(adapter); + adapter->webContents()->GetController().LoadURLWithParams(params); + adapter->focusIfNecessary(); + adapter->resetSelection(); + adapter->findTextHelper()->stopFinding(); +} + +void NavigateTask(QWeakPointer<WebContentsAdapter> weakAdapter, const content::NavigationController::LoadURLParams ¶ms) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + const auto adapter = weakAdapter.toStrongRef(); + if (!adapter) + return; + Navigate(adapter.get(), params); +} + static QList<WebContentsAdapter *> recursive_guard_loading_adapters; class LoadRecursionGuard { @@ -430,7 +453,7 @@ WebContentsAdapter::WebContentsAdapter() #endif , m_adapterClient(nullptr) , m_nextRequestId(CallbackDirectory::ReservedCallbackIdsEnd) - , m_currentDropAction(blink::kWebDragOperationNone) + , m_currentDropAction(blink::kDragOperationNone) , m_devToolsFrontend(nullptr) { // This has to be the first thing we create, and the last we destroy. @@ -446,7 +469,7 @@ WebContentsAdapter::WebContentsAdapter(std::unique_ptr<content::WebContents> web #endif , m_adapterClient(nullptr) , m_nextRequestId(CallbackDirectory::ReservedCallbackIdsEnd) - , m_currentDropAction(blink::kWebDragOperationNone) + , m_currentDropAction(blink::kDragOperationNone) , m_devToolsFrontend(nullptr) { // This has to be the first thing we create, and the last we destroy. @@ -484,7 +507,6 @@ void WebContentsAdapter::initialize(content::SiteInstance *site) // Create our own if a WebContents wasn't provided at construction. if (!m_webContents) { content::WebContents::CreateParams create_params(m_profileAdapter->profile(), site); - create_params.initial_size = gfx::Size(kTestWindowWidth, kTestWindowHeight); create_params.initially_hidden = true; m_webContents = content::WebContents::Create(create_params); } @@ -493,7 +515,7 @@ void WebContentsAdapter::initialize(content::SiteInstance *site) // Create and attach observers to the WebContents. m_webContentsDelegate.reset(new WebContentsDelegateQt(m_webContents.get(), m_adapterClient)); - m_renderViewObserverHost.reset(new RenderViewObserverHostQt(m_webContents.get(), m_adapterClient)); + m_pageHost.reset(new WebEnginePageHost(m_webContents.get(), m_adapterClient)); // Let the WebContent's view know about the WebContentsAdapterClient. WebContentsViewQt* contentsView = static_cast<WebContentsViewQt*>(static_cast<content::WebContentsImpl*>(m_webContents.get())->GetView()); @@ -519,7 +541,8 @@ void WebContentsAdapter::initialize(content::SiteInstance *site) content::RenderViewHost *rvh = m_webContents->GetRenderViewHost(); Q_ASSERT(rvh); if (!rvh->IsRenderViewLive()) - static_cast<content::WebContentsImpl*>(m_webContents.get())->CreateRenderViewForRenderManager(rvh, MSG_ROUTING_NONE, MSG_ROUTING_NONE, base::UnguessableToken::Create(), content::FrameReplicationState()); + static_cast<content::WebContentsImpl*>(m_webContents.get())->CreateRenderViewForRenderManager( + rvh, base::nullopt, MSG_ROUTING_NONE); m_webContentsDelegate->RenderViewHostChanged(nullptr, rvh); @@ -535,7 +558,7 @@ void WebContentsAdapter::initializeRenderPrefs() const int qtCursorFlashTime = QGuiApplication::styleHints()->cursorFlashTime(); rendererPrefs->caret_blink_interval = base::TimeDelta::FromMillisecondsD(0.5 * static_cast<double>(qtCursorFlashTime)); - rendererPrefs->user_agent_override = m_profileAdapter->httpUserAgent().toStdString(); + rendererPrefs->user_agent_override = blink::UserAgentOverride::UserAgentOnly(m_profileAdapter->httpUserAgent().toStdString()); rendererPrefs->accept_languages = m_profileAdapter->httpAcceptLanguageWithoutQualities().toStdString(); #if QT_CONFIG(webengine_webrtc) base::CommandLine* commandLine = base::CommandLine::ForCurrentProcess(); @@ -545,8 +568,8 @@ void WebContentsAdapter::initializeRenderPrefs() else rendererPrefs->webrtc_ip_handling_policy = m_adapterClient->webEngineSettings()->testAttribute(WebEngineSettings::WebRTCPublicInterfacesOnly) - ? content::kWebRTCIPHandlingDefaultPublicInterfaceOnly - : content::kWebRTCIPHandlingDefault; + ? blink::kWebRTCIPHandlingDefaultPublicInterfaceOnly + : blink::kWebRTCIPHandlingDefault; #endif // Set web-contents font settings to the default font settings as Chromium constantly overrides // the global font defaults with the font settings of the latest web-contents created. @@ -557,7 +580,7 @@ void WebContentsAdapter::initializeRenderPrefs() rendererPrefs->use_autohinter = params.autohinter; rendererPrefs->use_bitmaps = params.use_bitmaps; rendererPrefs->subpixel_rendering = params.subpixel_rendering; - m_webContents->GetRenderViewHost()->SyncRendererPrefs(); + m_webContents->SyncRendererPrefs(); } bool WebContentsAdapter::canGoBack() const @@ -581,8 +604,9 @@ bool WebContentsAdapter::canGoToOffset(int offset) const void WebContentsAdapter::stop() { CHECK_INITIALIZED(); - content::NavigationController& controller = m_webContents->GetController(); + base::RecordAction(base::UserMetricsAction("Stop")); + content::NavigationController& controller = m_webContents->GetController(); int index = controller.GetPendingEntryIndex(); if (index != -1) controller.RemoveEntryAtIndex(index); @@ -594,9 +618,13 @@ void WebContentsAdapter::stop() void WebContentsAdapter::reload() { CHECK_INITIALIZED(); + base::RecordAction(base::UserMetricsAction("Reload")); + bool wasDiscarded = (m_lifecycleState == LifecycleState::Discarded); setLifecycleState(LifecycleState::Active); CHECK_VALID_RENDER_WIDGET_HOST_VIEW(m_webContents->GetRenderViewHost()); + WebEngineSettings *settings = m_adapterClient->webEngineSettings(); + settings->doApply(); if (!wasDiscarded) // undiscard() already triggers a reload m_webContents->GetController().Reload(content::ReloadType::NORMAL, /*checkRepost = */false); focusIfNecessary(); @@ -605,9 +633,13 @@ void WebContentsAdapter::reload() void WebContentsAdapter::reloadAndBypassCache() { CHECK_INITIALIZED(); + base::RecordAction(base::UserMetricsAction("ReloadBypassingCache")); + bool wasDiscarded = (m_lifecycleState == LifecycleState::Discarded); setLifecycleState(LifecycleState::Active); CHECK_VALID_RENDER_WIDGET_HOST_VIEW(m_webContents->GetRenderViewHost()); + WebEngineSettings *settings = m_adapterClient->webEngineSettings(); + settings->doApply(); if (!wasDiscarded) // undiscard() already triggers a reload m_webContents->GetController().Reload(content::ReloadType::BYPASSING_CACHE, /*checkRepost = */false); focusIfNecessary(); @@ -627,6 +659,7 @@ void WebContentsAdapter::load(const QUrl &url) void WebContentsAdapter::load(const QWebEngineHttpRequest &request) { + base::RecordAction(base::UserMetricsAction("LoadURL")); GURL gurl = toGurl(request.url()); if (!isInitialized()) { scoped_refptr<content::SiteInstance> site = @@ -638,6 +671,9 @@ void WebContentsAdapter::load(const QWebEngineHttpRequest &request) CHECK_VALID_RENDER_WIDGET_HOST_VIEW(m_webContents->GetRenderViewHost()); + WebEngineSettings *settings = m_adapterClient->webEngineSettings(); + settings->doApply(); + // The situation can occur when relying on the editingFinished signal in QML to set the url // of the WebView. // When enter is pressed, onEditingFinished fires and the url of the webview is set, which @@ -678,9 +714,9 @@ void WebContentsAdapter::load(const QWebEngineHttpRequest &request) // chromium accepts LOAD_TYPE_HTTP_POST only for the HTTP and HTTPS protocols if (!params.url.SchemeIsHTTPOrHTTPS()) { m_adapterClient->loadFinished(false, request.url(), false, - net::ERR_DISALLOWED_URL_SCHEME, - QCoreApplication::translate("WebContentsAdapter", - "HTTP-POST data can only be sent over HTTP(S) protocol")); + net::ERR_DISALLOWED_URL_SCHEME, + QCoreApplication::translate("WebContentsAdapter", + "HTTP-POST data can only be sent over HTTP(S) protocol")); return; } params.post_data = network::ResourceRequestBody::CreateFromBytes( @@ -705,23 +741,12 @@ void WebContentsAdapter::load(const QWebEngineHttpRequest &request) } } - auto navigate = [](QWeakPointer<WebContentsAdapter> weakAdapter, const content::NavigationController::LoadURLParams ¶ms) { - const auto adapter = weakAdapter.toStrongRef(); - if (!adapter) - return; - adapter->webContents()->GetController().LoadURLWithParams(params); - // Follow chrome::Navigate and invalidate the URL immediately. - adapter->m_webContentsDelegate->NavigationStateChanged(adapter->webContents(), content::INVALIDATE_TYPE_URL); - adapter->focusIfNecessary(); - }; - - QWeakPointer<WebContentsAdapter> weakThis(sharedFromThis()); if (resizeNeeded) { // Schedule navigation on the event loop. - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(navigate, std::move(weakThis), std::move(params))); + base::PostTask(FROM_HERE, {content::BrowserThread::UI}, + base::BindOnce(&NavigateTask, sharedFromThis().toWeakRef(), std::move(params))); } else { - navigate(std::move(weakThis), params); + Navigate(this, params); } } @@ -734,6 +759,9 @@ void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeT CHECK_VALID_RENDER_WIDGET_HOST_VIEW(m_webContents->GetRenderViewHost()); + WebEngineSettings *settings = m_adapterClient->webEngineSettings(); + settings->doApply(); + QByteArray encodedData = data.toPercentEncoding(); std::string urlString; if (!mimeType.isEmpty()) @@ -744,7 +772,7 @@ void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeT GURL dataUrlToLoad(urlString); if (dataUrlToLoad.spec().size() > url::kMaxURLChars) { - m_adapterClient->loadFinished(false, baseUrl, false, net::ERR_ABORTED); + m_adapterClient->loadFinished(false, baseUrl, false, net::ERR_ABORTED, QString()); return; } content::NavigationController::LoadURLParams params((dataUrlToLoad)); @@ -754,14 +782,13 @@ void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeT params.can_load_local_resources = true; params.transition_type = ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_API); params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE; - m_webContents->GetController().LoadURLWithParams(params); - focusIfNecessary(); - m_webContents->CollapseSelection(); + Navigate(this, params); } void WebContentsAdapter::save(const QString &filePath, int savePageFormat) { CHECK_INITIALIZED(); + base::RecordAction(base::UserMetricsAction("SavePage")); m_webContentsDelegate->setSavePageInfo(SavePageInfo(filePath, savePageFormat)); m_webContents->OnSavePage(); } @@ -769,7 +796,7 @@ void WebContentsAdapter::save(const QString &filePath, int savePageFormat) QUrl WebContentsAdapter::activeUrl() const { CHECK_INITIALIZED(QUrl()); - return m_webContentsDelegate->url(); + return m_webContentsDelegate->url(webContents()); } QUrl WebContentsAdapter::requestedUrl() const @@ -816,42 +843,49 @@ QString WebContentsAdapter::selectedText() const void WebContentsAdapter::undo() { CHECK_INITIALIZED(); + base::RecordAction(base::UserMetricsAction("Undo")); m_webContents->Undo(); } void WebContentsAdapter::redo() { CHECK_INITIALIZED(); + base::RecordAction(base::UserMetricsAction("Redo")); m_webContents->Redo(); } void WebContentsAdapter::cut() { CHECK_INITIALIZED(); + base::RecordAction(base::UserMetricsAction("Cut")); m_webContents->Cut(); } void WebContentsAdapter::copy() { CHECK_INITIALIZED(); + base::RecordAction(base::UserMetricsAction("Copy")); m_webContents->Copy(); } void WebContentsAdapter::paste() { CHECK_INITIALIZED(); + base::RecordAction(base::UserMetricsAction("Paste")); m_webContents->Paste(); } void WebContentsAdapter::pasteAndMatchStyle() { CHECK_INITIALIZED(); + base::RecordAction(base::UserMetricsAction("PasteAndMatchStyle")); m_webContents->PasteAndMatchStyle(); } void WebContentsAdapter::selectAll() { CHECK_INITIALIZED(); + base::RecordAction(base::UserMetricsAction("SelectAll")); m_webContents->SelectAll(); } @@ -870,6 +904,7 @@ void WebContentsAdapter::unselect() void WebContentsAdapter::navigateBack() { CHECK_INITIALIZED(); + base::RecordAction(base::UserMetricsAction("Back")); CHECK_VALID_RENDER_WIDGET_HOST_VIEW(m_webContents->GetRenderViewHost()); if (!m_webContents->GetController().CanGoBack()) return; @@ -880,6 +915,7 @@ void WebContentsAdapter::navigateBack() void WebContentsAdapter::navigateForward() { CHECK_INITIALIZED(); + base::RecordAction(base::UserMetricsAction("Forward")); CHECK_VALID_RENDER_WIDGET_HOST_VIEW(m_webContents->GetRenderViewHost()); if (!m_webContents->GetController().CanGoForward()) return; @@ -969,10 +1005,10 @@ void WebContentsAdapter::serializeNavigationHistory(QDataStream &output) void WebContentsAdapter::setZoomFactor(qreal factor) { CHECK_INITIALIZED(); - if (factor < content::kMinimumZoomFactor || factor > content::kMaximumZoomFactor) + if (factor < blink::kMinimumPageZoomFactor || factor > blink::kMaximumPageZoomFactor) return; - double zoomLevel = content::ZoomFactorToZoomLevel(static_cast<double>(factor)); + double zoomLevel = blink::PageZoomFactorToZoomLevel(static_cast<double>(factor)); content::HostZoomMap *zoomMap = content::HostZoomMap::GetForWebContents(m_webContents.get()); if (zoomMap) { @@ -985,7 +1021,7 @@ void WebContentsAdapter::setZoomFactor(qreal factor) qreal WebContentsAdapter::currentZoomFactor() const { CHECK_INITIALIZED(1); - return content::ZoomLevelToZoomFactor(content::HostZoomMap::GetZoomLevel(m_webContents.get())); + return blink::PageZoomLevelToZoomFactor(content::HostZoomMap::GetZoomLevel(m_webContents.get())); } ProfileQt* WebContentsAdapter::profile() @@ -1000,20 +1036,33 @@ ProfileAdapter* WebContentsAdapter::profileAdapter() static_cast<ProfileQt*>(m_webContents->GetBrowserContext())->profileAdapter() : nullptr; } -#ifndef QT_NO_ACCESSIBILITY +void WebContentsAdapter::setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor) +{ + m_requestInterceptor = interceptor; +} + +QWebEngineUrlRequestInterceptor* WebContentsAdapter::requestInterceptor() const +{ + return m_requestInterceptor; +} + +#if QT_CONFIG(accessibility) QAccessibleInterface *WebContentsAdapter::browserAccessible() { CHECK_INITIALIZED(nullptr); content::RenderViewHost *rvh = m_webContents->GetRenderViewHost(); Q_ASSERT(rvh); - content::BrowserAccessibilityManager *manager = static_cast<content::RenderFrameHostImpl*>(rvh->GetMainFrame())->GetOrCreateBrowserAccessibilityManager(); + content::RenderFrameHostImpl *rfh = static_cast<content::RenderFrameHostImpl *>(rvh->GetMainFrame()); + if (!rfh) + return nullptr; + content::BrowserAccessibilityManager *manager = rfh->GetOrCreateBrowserAccessibilityManager(); if (!manager) // FIXME! return nullptr; content::BrowserAccessibility *acc = manager->GetRoot(); return content::toQAccessibleInterface(acc); } -#endif // QT_NO_ACCESSIBILITY +#endif // QT_CONFIG(accessibility) void WebContentsAdapter::runJavaScript(const QString &javaScript, quint32 worldId) { @@ -1021,13 +1070,10 @@ void WebContentsAdapter::runJavaScript(const QString &javaScript, quint32 worldI content::RenderViewHost *rvh = m_webContents->GetRenderViewHost(); Q_ASSERT(rvh); // static_cast<content::RenderFrameHostImpl *>(rvh->GetMainFrame())->NotifyUserActivation(); - if (worldId == 0) { + if (worldId == 0) rvh->GetMainFrame()->ExecuteJavaScript(toString16(javaScript), base::NullCallback()); - return; - } - - content::RenderFrameHost::JavaScriptResultCallback callback = base::BindOnce(&callbackOnEvaluateJS, m_adapterClient, CallbackDirectory::NoCallbackId); - rvh->GetMainFrame()->ExecuteJavaScriptInIsolatedWorld(toString16(javaScript), std::move(callback), worldId); + else + rvh->GetMainFrame()->ExecuteJavaScriptInIsolatedWorld(toString16(javaScript), base::NullCallback(), worldId); } quint64 WebContentsAdapter::runJavaScriptCallbackResult(const QString &javaScript, quint32 worldId) @@ -1047,21 +1093,21 @@ quint64 WebContentsAdapter::runJavaScriptCallbackResult(const QString &javaScrip quint64 WebContentsAdapter::fetchDocumentMarkup() { CHECK_INITIALIZED(0); - m_renderViewObserverHost->fetchDocumentMarkup(m_nextRequestId); + m_pageHost->FetchDocumentMarkup(m_nextRequestId); return m_nextRequestId++; } quint64 WebContentsAdapter::fetchDocumentInnerText() { CHECK_INITIALIZED(0); - m_renderViewObserverHost->fetchDocumentInnerText(m_nextRequestId); + m_pageHost->FetchDocumentInnerText(m_nextRequestId); return m_nextRequestId++; } -void WebContentsAdapter::updateWebPreferences(const content::WebPreferences & webPreferences) +void WebContentsAdapter::updateWebPreferences(const blink::web_pref::WebPreferences &webPreferences) { CHECK_INITIALIZED(); - m_webContents->GetRenderViewHost()->UpdateWebkitPreferences(webPreferences); + m_webContents->SetWebPreferences(webPreferences); // In case of updating preferences during navigation, there might be a pending RVH what will // be active on successful navigation. @@ -1069,7 +1115,7 @@ void WebContentsAdapter::updateWebPreferences(const content::WebPreferences & we if (pendingRFH) { content::RenderViewHost *pendingRVH = pendingRFH->GetRenderViewHost(); Q_ASSERT(pendingRVH); - pendingRVH->UpdateWebkitPreferences(webPreferences); + static_cast<content::RenderViewHostImpl*>(pendingRVH)->SendWebPreferencesToRenderer(); } } @@ -1141,28 +1187,39 @@ bool WebContentsAdapter::recentlyAudible() const return m_webContents->IsCurrentlyAudible(); } +qint64 WebContentsAdapter::renderProcessPid() const +{ + CHECK_INITIALIZED(0); + + content::RenderProcessHost *renderProcessHost = m_webContents->GetMainFrame()->GetProcess(); + const base::Process &process = renderProcessHost->GetProcess(); + if (!process.IsValid()) + return 0; + return process.Pid(); +} + void WebContentsAdapter::copyImageAt(const QPoint &location) { CHECK_INITIALIZED(); m_webContents->GetRenderViewHost()->GetMainFrame()->CopyImageAt(location.x(), location.y()); } -static blink::WebMediaPlayerAction::Type toBlinkMediaPlayerActionType(WebContentsAdapter::MediaPlayerAction action) +static blink::mojom::MediaPlayerActionType toBlinkMediaPlayerActionType(WebContentsAdapter::MediaPlayerAction action) { switch (action) { case WebContentsAdapter::MediaPlayerPlay: - return blink::WebMediaPlayerAction::Type::kPlay; + return blink::mojom::MediaPlayerActionType::kPlay; case WebContentsAdapter::MediaPlayerMute: - return blink::WebMediaPlayerAction::Type::kMute; + return blink::mojom::MediaPlayerActionType::kMute; case WebContentsAdapter::MediaPlayerLoop: - return blink::WebMediaPlayerAction::Type::kLoop; + return blink::mojom::MediaPlayerActionType::kLoop; case WebContentsAdapter::MediaPlayerControls: - return blink::WebMediaPlayerAction::Type::kControls; + return blink::mojom::MediaPlayerActionType::kControls; case WebContentsAdapter::MediaPlayerNoAction: break; } NOTREACHED(); - return (blink::WebMediaPlayerAction::Type)-1; + return (blink::mojom::MediaPlayerActionType)-1; } void WebContentsAdapter::executeMediaPlayerActionAt(const QPoint &location, MediaPlayerAction action, bool enable) @@ -1170,7 +1227,7 @@ void WebContentsAdapter::executeMediaPlayerActionAt(const QPoint &location, Medi CHECK_INITIALIZED(); if (action == MediaPlayerNoAction) return; - blink::WebMediaPlayerAction blinkAction(toBlinkMediaPlayerActionType(action), enable); + blink::mojom::MediaPlayerAction blinkAction(toBlinkMediaPlayerActionType(action), enable); m_webContents->GetRenderViewHost()->GetMainFrame()->ExecuteMediaPlayerActionAtLocation(toGfx(location), blinkAction); } @@ -1245,12 +1302,14 @@ void WebContentsAdapter::devToolsFrontendDestroyed(DevToolsFrontendQt *frontend) void WebContentsAdapter::exitFullScreen() { CHECK_INITIALIZED(); + base::RecordAction(base::UserMetricsAction("ToggleFullscreen")); m_webContents->ExitFullscreen(false); } void WebContentsAdapter::changedFullScreen() { CHECK_INITIALIZED(); + base::RecordAction(base::UserMetricsAction("ToggleFullscreen")); m_webContents->NotifyFullscreenChanged(false); } @@ -1273,10 +1332,13 @@ void WebContentsAdapter::printToPDF(const QPageLayout &pageLayout, const QString PrintViewManagerQt::PrintToPDFFileCallback callback = base::Bind(&callbackOnPdfSavingFinished, m_adapterClient, filePath); - PrintViewManagerQt::FromWebContents(m_webContents.get())->PrintToPDFFileWithCallback(pageLayout, - true, - filePath, - callback); + content::WebContents *webContents = m_webContents.get(); + if (content::WebContents *guest = guestWebContents()) + webContents = guest; + PrintViewManagerQt::FromWebContents(webContents)->PrintToPDFFileWithCallback(pageLayout, + true, + filePath, + callback); #endif // QT_CONFIG(webengine_printing_and_pdf) } @@ -1289,10 +1351,13 @@ quint64 WebContentsAdapter::printToPDFCallbackResult(const QPageLayout &pageLayo PrintViewManagerQt::PrintToPDFCallback callback = base::Bind(&callbackOnPrintingFinished, m_adapterClient, m_nextRequestId); - PrintViewManagerQt::FromWebContents(m_webContents.get())->PrintToPDFWithCallback(pageLayout, - colorMode, - useCustomMargins, - callback); + content::WebContents *webContents = m_webContents.get(); + if (content::WebContents *guest = guestWebContents()) + webContents = guest; + PrintViewManagerQt::FromWebContents(webContents)->PrintToPDFWithCallback(pageLayout, + colorMode, + useCustomMargins, + callback); return m_nextRequestId++; #else Q_UNUSED(pageLayout); @@ -1322,43 +1387,62 @@ void WebContentsAdapter::grantMediaAccessPermission(const QUrl &securityOrigin, CHECK_INITIALIZED(); // Let the permission manager remember the reply. if (flags & WebContentsAdapterClient::MediaAudioCapture) - m_profileAdapter->permissionRequestReply(securityOrigin, ProfileAdapter::AudioCapturePermission, true); + m_profileAdapter->permissionRequestReply(securityOrigin, ProfileAdapter::AudioCapturePermission, ProfileAdapter::AllowedPermission); if (flags & WebContentsAdapterClient::MediaVideoCapture) - m_profileAdapter->permissionRequestReply(securityOrigin, ProfileAdapter::VideoCapturePermission, true); + m_profileAdapter->permissionRequestReply(securityOrigin, ProfileAdapter::VideoCapturePermission, ProfileAdapter::AllowedPermission); MediaCaptureDevicesDispatcher::GetInstance()->handleMediaAccessPermissionResponse(m_webContents.get(), securityOrigin, flags); } -void WebContentsAdapter::runGeolocationRequestCallback(const QUrl &securityOrigin, bool allowed) +void WebContentsAdapter::grantFeaturePermission(const QUrl &securityOrigin, ProfileAdapter::PermissionType feature, ProfileAdapter::PermissionState allowed) { - CHECK_INITIALIZED(); - m_profileAdapter->permissionRequestReply(securityOrigin, ProfileAdapter::GeolocationPermission, allowed); -} - -void WebContentsAdapter::runUserNotificationRequestCallback(const QUrl &securityOrigin, bool allowed) -{ - CHECK_INITIALIZED(); - m_profileAdapter->permissionRequestReply(securityOrigin, ProfileAdapter::NotificationPermission, allowed); + Q_ASSERT(m_profileAdapter); + m_profileAdapter->permissionRequestReply(securityOrigin, feature, allowed); } -void WebContentsAdapter::grantMouseLockPermission(bool granted) +void WebContentsAdapter::grantMouseLockPermission(const QUrl &securityOrigin, bool granted) { CHECK_INITIALIZED(); + if (securityOrigin != toQt(m_webContents->GetLastCommittedURL().GetOrigin())) + return; if (granted) { - if (RenderWidgetHostViewQt *rwhv = static_cast<RenderWidgetHostViewQt *>(m_webContents->GetRenderWidgetHostView())) + if (RenderWidgetHostViewQt *rwhv = static_cast<RenderWidgetHostViewQt *>(m_webContents->GetRenderWidgetHostView())) { rwhv->Focus(); - else + if (!rwhv->HasFocus()) { + // We tried to activate our RWHVQtDelegate, but we failed. This probably means that + // the permission was granted from a modal dialog and the windowing system is not ready + // to set focus on the originating view. Since pointer lock strongly requires it, we just + // wait until the next FocusIn event. + m_pendingMouseLockPermissions.insert(securityOrigin, granted); + return; + } + } else granted = false; } - m_webContents->GotResponseToLockMouseRequest(granted); + m_webContents->GotResponseToLockMouseRequest(granted ? blink::mojom::PointerLockResult::kSuccess + : blink::mojom::PointerLockResult::kPermissionDenied); +} + +void WebContentsAdapter::handlePendingMouseLockPermission() +{ + CHECK_INITIALIZED(); + auto it = m_pendingMouseLockPermissions.find(toQt(m_webContents->GetLastCommittedURL().GetOrigin())); + if (it != m_pendingMouseLockPermissions.end()) { + m_webContents->GotResponseToLockMouseRequest(it.value() ? blink::mojom::PointerLockResult::kSuccess + : blink::mojom::PointerLockResult::kPermissionDenied); + m_pendingMouseLockPermissions.erase(it); + } } void WebContentsAdapter::setBackgroundColor(const QColor &color) { CHECK_INITIALIZED(); + SkColor c = toSk(color); if (content::RenderWidgetHostView *rwhv = m_webContents->GetRenderWidgetHostView()) - rwhv->SetBackgroundColor(toSk(color)); + rwhv->SetBackgroundColor(c); + if (color != Qt::transparent) + m_pageHost->SetBackgroundColor(c); } content::WebContents *WebContentsAdapter::webContents() const @@ -1366,6 +1450,12 @@ content::WebContents *WebContentsAdapter::webContents() const return m_webContents.get(); } +content::WebContents *WebContentsAdapter::guestWebContents() const +{ + std::vector<content::WebContents *> innerWebContents = m_webContents->GetInnerWebContents(); + return !innerWebContents.empty() ? innerWebContents[0] : nullptr; +} + #if QT_CONFIG(webengine_webchannel) QWebChannel *WebContentsAdapter::webChannel() const { @@ -1402,12 +1492,14 @@ void WebContentsAdapter::setWebChannel(QWebChannel *channel, uint worldId) static QMimeData *mimeDataFromDropData(const content::DropData &dropData) { QMimeData *mimeData = new QMimeData(); - if (!dropData.text.is_null()) - mimeData->setText(toQt(dropData.text.string())); - if (!dropData.html.is_null()) - mimeData->setHtml(toQt(dropData.html.string())); - if (dropData.url.is_valid()) + if (dropData.text.has_value()) + mimeData->setText(toQt(*dropData.text)); + if (dropData.html.has_value()) + mimeData->setHtml(toQt(*dropData.html)); + if (dropData.url.is_valid()) { mimeData->setUrls(QList<QUrl>() << toQt(dropData.url)); + mimeData->setText(toQt(dropData.url_title)); + } if (!dropData.custom_data.empty()) { base::Pickle pickle; ui::WriteCustomDataToPickle(dropData.custom_data, &pickle); @@ -1416,16 +1508,16 @@ static QMimeData *mimeDataFromDropData(const content::DropData &dropData) return mimeData; } -static blink::WebDragOperationsMask toWeb(const Qt::DropActions action) +static blink::DragOperationsMask toWeb(const Qt::DropActions action) { - int result = blink::kWebDragOperationNone; + int result = blink::kDragOperationNone; if (action & Qt::CopyAction) - result |= blink::kWebDragOperationCopy; + result |= blink::kDragOperationCopy; if (action & Qt::LinkAction) - result |= blink::kWebDragOperationLink; + result |= blink::kDragOperationLink; if (action & Qt::MoveAction) - result |= blink::kWebDragOperationMove; - return static_cast<blink::WebDragOperationsMask>(result); + result |= blink::kDragOperationMove; + return static_cast<blink::DragOperationsMask>(result); } void WebContentsAdapter::startDragging(QObject *dragSource, const content::DropData &dropData, @@ -1444,7 +1536,7 @@ void WebContentsAdapter::startDragging(QObject *dragSource, const content::DropD m_currentDropData->file_contents.clear(); m_currentDropData->file_contents_content_disposition.clear(); - m_currentDropAction = blink::kWebDragOperationNone; + m_currentDropAction = blink::kDragOperationNone; QDrag *drag = new QDrag(dragSource); // will be deleted by Qt's DnD implementation bool dValid = true; QMetaObject::Connection onDestroyed = QObject::connect(dragSource, &QObject::destroyed, [&dValid](){ @@ -1462,18 +1554,25 @@ void WebContentsAdapter::startDragging(QObject *dragSource, const content::DropD } { - base::MessageLoopCurrent::ScopedNestableTaskAllower allow; + base::CurrentThread::ScopedNestableTaskAllower allow; drag->exec(allowedActions); } QObject::disconnect(onDestroyed); if (dValid) { if (m_webContents) { - content::RenderViewHost *rvh = m_webContents->GetRenderViewHost(); + // This is the quickest and (at the moment) the most safe solution to not break guest views when + // dropping data into them. We don't even try to support dropping into PDF input fields, + // since it's not working in Chrome right now. + content::WebContents *targetWebContents = m_webContents.get(); + if (content::WebContents *guest = guestWebContents()) + targetWebContents = guest; + + content::RenderViewHost *rvh = targetWebContents->GetRenderViewHost(); if (rvh) { rvh->GetWidget()->DragSourceEndedAt(gfx::PointF(m_lastDragClientPos.x(), m_lastDragClientPos.y()), gfx::PointF(m_lastDragScreenPos.x(), m_lastDragScreenPos.y()), - blink::WebDragOperation(m_currentDropAction)); + blink::DragOperation(m_currentDropAction)); rvh->GetWidget()->DragSourceSystemDragEnded(); } } @@ -1524,23 +1623,28 @@ static void fillDropDataFromMimeData(content::DropData *dropData, const QMimeDat } if (!dropData->filenames.empty()) return; + if (mimeData->hasUrls()) { + dropData->url = toGurl(urls.first()); + if (mimeData->hasText()) + dropData->url_title = toString16(mimeData->text()); + } if (mimeData->hasHtml()) - dropData->html = toNullableString16(mimeData->html()); + dropData->html = toOptionalString16(mimeData->html()); if (mimeData->hasText()) - dropData->text = toNullableString16(mimeData->text()); + dropData->text = toOptionalString16(mimeData->text()); if (mimeData->hasFormat(QLatin1String(ui::kMimeTypeWebCustomData))) { QByteArray customData = mimeData->data(QLatin1String(ui::kMimeTypeWebCustomData)); ui::ReadCustomDataIntoMap(customData.constData(), customData.length(), &dropData->custom_data); } } -Qt::DropAction toQt(blink::WebDragOperation op) +Qt::DropAction toQt(blink::DragOperation op) { - if (op & blink::kWebDragOperationCopy) + if (op & blink::kDragOperationCopy) return Qt::CopyAction; - if (op & blink::kWebDragOperationLink) + if (op & blink::kDragOperationLink) return Qt::LinkAction; - if (op & blink::kWebDragOperationMove || op & blink::kWebDragOperationDelete) + if (op & blink::kDragOperationMove || op & blink::kDragOperationDelete) return Qt::MoveAction; return Qt::IgnoreAction; } @@ -1597,7 +1701,7 @@ Qt::DropAction WebContentsAdapter::updateDragPosition(QDragMoveEvent *e, const Q rvh->GetWidget()->DragTargetDragOver(toGfx(m_lastDragClientPos), toGfx(m_lastDragScreenPos), toWeb(e->possibleActions()), toWeb(e->mouseButtons()) | toWeb(e->keyboardModifiers())); waitForUpdateDragActionCalled(); - return toQt(blink::WebDragOperation(m_currentDropAction)); + return toQt(blink::DragOperation(m_currentDropAction)); } void WebContentsAdapter::waitForUpdateDragActionCalled() @@ -1606,7 +1710,7 @@ void WebContentsAdapter::waitForUpdateDragActionCalled() const qint64 timeout = 3000; QElapsedTimer t; t.start(); - auto seqMan = base::MessageLoopCurrent::GetCurrentSequenceManagerImpl(); + auto seqMan = base::CurrentThread::GetCurrentSequenceManagerImpl(); base::MessagePump::Delegate *delegate = static_cast<base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl *>( seqMan->controller_.get()); @@ -1614,7 +1718,7 @@ void WebContentsAdapter::waitForUpdateDragActionCalled() DCHECK(delegate); m_updateDragActionCalled = false; for (;;) { - while (delegate->DoWork() && !m_updateDragActionCalled) {} + while (delegate->DoWork().is_immediate() && !m_updateDragActionCalled) {} if (m_updateDragActionCalled) break; if (t.hasExpired(timeout)) { @@ -1630,7 +1734,7 @@ void WebContentsAdapter::updateDragAction(int action) { CHECK_INITIALIZED(); m_updateDragActionCalled = true; - m_currentDropAction = static_cast<blink::WebDragOperation>(action); + m_currentDropAction = static_cast<blink::DragOperation>(action); } void WebContentsAdapter::endDragging(QDropEvent *e, const QPointF &screenPos) @@ -1678,6 +1782,17 @@ bool WebContentsAdapter::hasFocusedFrame() const return m_webContents->GetFocusedFrame() != nullptr; } +void WebContentsAdapter::resetSelection() +{ + CHECK_INITIALIZED(); + // unconditionally clears the selection in contrast to CollapseSelection, which checks focus state first + if (auto rwhv = static_cast<RenderWidgetHostViewQt *>(m_webContents->GetRenderWidgetHostView())) { + if (auto mgr = rwhv->GetTextInputManager()) + if (auto selection = const_cast<content::TextInputManager::TextSelection *>(mgr->GetTextSelection(rwhv))) + selection->SetSelection(base::string16(), 0, gfx::Range(), false); + } +} + WebContentsAdapterClient::RenderProcessTerminationStatus WebContentsAdapterClient::renderProcessExitStatus(int terminationStatus) { auto status = WebContentsAdapterClient::RenderProcessTerminationStatus(-1); @@ -1724,6 +1839,7 @@ FindTextHelper *WebContentsAdapter::findTextHelper() void WebContentsAdapter::viewSource() { CHECK_INITIALIZED(); + base::RecordAction(base::UserMetricsAction("ViewSource")); m_webContents->GetMainFrame()->ViewSource(); } @@ -1830,7 +1946,7 @@ WebContentsAdapter::LifecycleState WebContentsAdapter::determineRecommendedState return LifecycleState::Frozen; // Form input is not saved. - if (m_webContents->GetPageImportanceSignals().had_form_interaction) + if (FormInteractionTabHelper::FromWebContents(m_webContents.get())->had_form_interaction()) return LifecycleState::Frozen; // Do not discard PDFs as they might contain entry that is not saved and they @@ -1894,8 +2010,9 @@ void WebContentsAdapter::discard() // Based on TabLifecycleUnitSource::TabLifecycleUnit::FinishDiscard if (m_webContents->IsLoading()) { - m_webContentsDelegate->didFailLoad(m_webContentsDelegate->url(), net::Error::ERR_ABORTED, + m_webContentsDelegate->didFailLoad(m_webContentsDelegate->url(webContents()), net::Error::ERR_ABORTED, QStringLiteral("Discarded")); + m_webContentsDelegate->DidStopLoading(); } content::WebContents::CreateParams createParams(m_profileAdapter->profile()); @@ -1921,14 +2038,14 @@ void WebContentsAdapter::discard() m_webChannel = nullptr; m_webChannelWorld = 0; #endif - m_renderViewObserverHost.reset(); + m_pageHost.reset(); m_webContentsDelegate.reset(); m_webContents.reset(); m_webContents = std::move(nullContents); initializeRenderPrefs(); m_webContentsDelegate = std::move(nullDelegate); - m_renderViewObserverHost.reset(new RenderViewObserverHostQt(m_webContents.get(), m_adapterClient)); + m_pageHost.reset(new WebEnginePageHost(m_webContents.get(), m_adapterClient)); WebContentsViewQt *contentsView = static_cast<WebContentsViewQt *>(static_cast<content::WebContentsImpl *>(m_webContents.get())->GetView()); contentsView->setClient(m_adapterClient); @@ -1949,9 +2066,7 @@ void WebContentsAdapter::undiscard() Q_ASSERT(rvh); if (!rvh->IsRenderViewLive()) static_cast<content::WebContentsImpl *>(m_webContents.get()) - ->CreateRenderViewForRenderManager(rvh, MSG_ROUTING_NONE, MSG_ROUTING_NONE, - base::UnguessableToken::Create(), - content::FrameReplicationState()); + ->CreateRenderViewForRenderManager(rvh, base::nullopt, MSG_ROUTING_NONE); m_webContentsDelegate->RenderViewHostChanged(nullptr, rvh); m_adapterClient->initializationFinished(); m_adapterClient->selectionChanged(); @@ -1974,9 +2089,9 @@ ASSERT_ENUMS_MATCH(ReferrerPolicy::NoReferrerWhenDowngrade, network::mojom::Refe ASSERT_ENUMS_MATCH(ReferrerPolicy::Never, network::mojom::ReferrerPolicy::kNever) ASSERT_ENUMS_MATCH(ReferrerPolicy::Origin, network::mojom::ReferrerPolicy::kOrigin) ASSERT_ENUMS_MATCH(ReferrerPolicy::OriginWhenCrossOrigin, network::mojom::ReferrerPolicy::kOriginWhenCrossOrigin) -ASSERT_ENUMS_MATCH(ReferrerPolicy::NoReferrerWhenDowngradeOriginWhenCrossOrigin, network::mojom::ReferrerPolicy::kNoReferrerWhenDowngradeOriginWhenCrossOrigin) +//ASSERT_ENUMS_MATCH(ReferrerPolicy::NoReferrerWhenDowngradeOriginWhenCrossOrigin, network::mojom::ReferrerPolicy::kNoReferrerWhenDowngradeOriginWhenCrossOrigin) ASSERT_ENUMS_MATCH(ReferrerPolicy::SameOrigin, network::mojom::ReferrerPolicy::kSameOrigin) ASSERT_ENUMS_MATCH(ReferrerPolicy::StrictOrigin, network::mojom::ReferrerPolicy::kStrictOrigin) -ASSERT_ENUMS_MATCH(ReferrerPolicy::Last, network::mojom::ReferrerPolicy::kLast) +ASSERT_ENUMS_MATCH(ReferrerPolicy::Last, network::mojom::ReferrerPolicy::kMaxValue) } // namespace QtWebEngineCore diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h index 11f8f9cb1..ba02a0418 100644 --- a/src/core/web_contents_adapter.h +++ b/src/core/web_contents_adapter.h @@ -61,10 +61,16 @@ #include <QSharedPointer> #include <QString> #include <QUrl> +#include <QPointer> + +namespace blink { +namespace web_pref { +struct WebPreferences; +} +} namespace content { class WebContents; -struct WebPreferences; struct OpenURLParams; class SiteInstance; } @@ -79,6 +85,7 @@ class QPageLayout; class QString; class QTemporaryDir; class QWebChannel; +class QWebEngineUrlRequestInterceptor; QT_END_NAMESPACE namespace QtWebEngineCore { @@ -88,7 +95,7 @@ class FaviconManager; class FindTextHelper; class MessagePassingInterface; class ProfileQt; -class RenderViewObserverHostQt; +class WebEnginePageHost; class WebChannelIPCTransportHost; class WebEngineContext; @@ -159,13 +166,14 @@ public: quint64 runJavaScriptCallbackResult(const QString &javaScript, quint32 worldId); quint64 fetchDocumentMarkup(); quint64 fetchDocumentInnerText(); - void updateWebPreferences(const content::WebPreferences &webPreferences); + void updateWebPreferences(const blink::web_pref::WebPreferences &webPreferences); void download(const QUrl &url, const QString &suggestedFileName, const QUrl &referrerUrl = QUrl(), ReferrerPolicy referrerPolicy = ReferrerPolicy::Default); bool isAudioMuted() const; void setAudioMuted(bool mute); bool recentlyAudible() const; + qint64 renderProcessPid() const; // Must match blink::WebMediaPlayerAction::Type. enum MediaPlayerAction { @@ -191,9 +199,9 @@ public: void devToolsFrontendDestroyed(DevToolsFrontendQt *frontend); void grantMediaAccessPermission(const QUrl &securityOrigin, WebContentsAdapterClient::MediaRequestFlags flags); - void runGeolocationRequestCallback(const QUrl &securityOrigin, bool allowed); - void grantMouseLockPermission(bool granted); - void runUserNotificationRequestCallback(const QUrl &securityOrigin, bool allowed); + void grantMouseLockPermission(const QUrl &securityOrigin, bool granted); + void handlePendingMouseLockPermission(); + void grantFeaturePermission(const QUrl &securityOrigin, ProfileAdapter::PermissionType feature, ProfileAdapter::PermissionState allowed); void setBackgroundColor(const QColor &color); QAccessibleInterface *browserAccessible(); @@ -229,11 +237,15 @@ public: void focusIfNecessary(); bool isFindTextInProgress() const; bool hasFocusedFrame() const; + void resetSelection(); // meant to be used within WebEngineCore only void initialize(content::SiteInstance *site); content::WebContents *webContents() const; + content::WebContents *guestWebContents() const; void updateRecommendedState(); + void setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor); + QWebEngineUrlRequestInterceptor* requestInterceptor() const; private: Q_DISABLE_COPY(WebContentsAdapter) @@ -255,7 +267,7 @@ private: ProfileAdapter *m_profileAdapter; std::unique_ptr<content::WebContents> m_webContents; std::unique_ptr<WebContentsDelegateQt> m_webContentsDelegate; - std::unique_ptr<RenderViewObserverHostQt> m_renderViewObserverHost; + std::unique_ptr<WebEnginePageHost> m_pageHost; #if QT_CONFIG(webengine_webchannel) std::unique_ptr<WebChannelIPCTransportHost> m_webChannelTransport; QWebChannel *m_webChannel; @@ -263,6 +275,7 @@ private: #endif WebContentsAdapterClient *m_adapterClient; quint64 m_nextRequestId; + QMap<QUrl, bool> m_pendingMouseLockPermissions; std::unique_ptr<content::DropData> m_currentDropData; uint m_currentDropAction; bool m_updateDragActionCalled; @@ -273,6 +286,7 @@ private: LifecycleState m_lifecycleState = LifecycleState::Active; LifecycleState m_recommendedState = LifecycleState::Active; bool m_inspector = false; + QPointer<QWebEngineUrlRequestInterceptor> m_requestInterceptor; }; } // namespace QtWebEngineCore diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h index 75fb112c6..8203ce650 100644 --- a/src/core/web_contents_adapter_client.h +++ b/src/core/web_contents_adapter_client.h @@ -53,6 +53,8 @@ #include "qtwebenginecoreglobal_p.h" +#include "profile_adapter.h" + #include <QFlags> #include <QRect> #include <QSharedPointer> @@ -68,6 +70,7 @@ QT_FORWARD_DECLARE_CLASS(QWebEngineFindTextResult) QT_FORWARD_DECLARE_CLASS(QWebEngineQuotaRequest) QT_FORWARD_DECLARE_CLASS(QWebEngineRegisterProtocolHandlerRequest) QT_FORWARD_DECLARE_CLASS(QWebEngineUrlRequestInfo) +QT_FORWARD_DECLARE_CLASS(QWebEngineUrlRequestInterceptor) namespace content { struct DropData; @@ -76,7 +79,6 @@ struct DropData; namespace QtWebEngineCore { class AuthenticationDialogController; -class ProfileAdapter; class ColorChooserController; class FilePickerController; class JavaScriptDialogController; @@ -452,21 +454,26 @@ public: virtual void recommendedStateChanged(LifecycleState) = 0; virtual void visibleChanged(bool) = 0; virtual void titleChanged(const QString&) = 0; - virtual void urlChanged(const QUrl&) = 0; + virtual void urlChanged() = 0; virtual void iconChanged(const QUrl&) = 0; virtual void loadProgressChanged(int progress) = 0; virtual void didUpdateTargetURL(const QUrl&) = 0; virtual void selectionChanged() = 0; + virtual void zoomUpdateIsNeeded() = 0; virtual void recentlyAudibleChanged(bool recentlyAudible) = 0; + virtual void renderProcessPidChanged(qint64 pid) = 0; virtual QRectF viewportRect() const = 0; virtual QColor backgroundColor() const = 0; virtual void loadStarted(const QUrl &provisionalUrl, bool isErrorPage = false) = 0; virtual void loadCommitted() = 0; virtual void loadVisuallyCommitted() = 0; - virtual void loadFinished(bool success, const QUrl &url, bool isErrorPage = false, int errorCode = 0, const QString &errorDescription = QString()) = 0; + virtual void loadFinished(bool success, const QUrl &url, bool isErrorPage, int errorCode, const QString &errorDescription) = 0; virtual void focusContainer() = 0; virtual void unhandledKeyEvent(QKeyEvent *event) = 0; - virtual void adoptNewWindow(QSharedPointer<WebContentsAdapter> newWebContents, WindowOpenDisposition disposition, bool userGesture, const QRect & initialGeometry, const QUrl &targetUrl) = 0; + virtual QSharedPointer<WebContentsAdapter> + adoptNewWindow(QSharedPointer<WebContentsAdapter> newWebContents, + WindowOpenDisposition disposition, bool userGesture, + const QRect &initialGeometry, const QUrl &targetUrl) = 0; virtual bool isBeingAdopted() = 0; virtual void close() = 0; virtual void windowCloseRejected() = 0; @@ -488,12 +495,11 @@ public: virtual QObject *accessibilityParentObject() = 0; virtual void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) = 0; virtual void authenticationRequired(QSharedPointer<AuthenticationDialogController>) = 0; - virtual void runGeolocationPermissionRequest(const QUrl &securityOrigin) = 0; + virtual void runFeaturePermissionRequest(ProfileAdapter::PermissionType, const QUrl &securityOrigin) = 0; virtual void runMediaAccessPermissionRequest(const QUrl &securityOrigin, MediaRequestFlags requestFlags) = 0; virtual void runMouseLockPermissionRequest(const QUrl &securityOrigin) = 0; virtual void runQuotaRequest(QWebEngineQuotaRequest) = 0; virtual void runRegisterProtocolHandlerRequest(QWebEngineRegisterProtocolHandlerRequest) = 0; - virtual void runUserNotificationPermissionRequest(const QUrl &securityOrigin) = 0; virtual WebEngineSettings *webEngineSettings() const = 0; RenderProcessTerminationStatus renderProcessExitStatus(int); virtual void renderProcessTerminated(RenderProcessTerminationStatus terminationStatus, int exitCode) = 0; @@ -513,7 +519,6 @@ public: virtual ClientType clientType() = 0; virtual void printRequested() = 0; virtual void widgetChanged(RenderWidgetHostViewQtDelegate *newWidget) = 0; - virtual void interceptRequest(QWebEngineUrlRequestInfo &) { } virtual TouchHandleDrawableClient *createTouchHandle(const QMap<int, QImage> &images) = 0; virtual void showTouchSelectionMenu(TouchSelectionMenuController *menuController, const QRect &bounds, const QSize &handleSize) = 0; virtual void hideTouchSelectionMenu() = 0; @@ -522,7 +527,6 @@ public: virtual ProfileAdapter *profileAdapter() = 0; virtual WebContentsAdapter* webContentsAdapter() = 0; virtual void releaseProfile() = 0; - }; } // namespace QtWebEngineCore diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index 2a89556cf..d211bdbfc 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -49,7 +49,6 @@ #include "favicon_manager.h" #include "file_picker_controller.h" #include "media_capture_devices_dispatcher.h" -#include "net/network_delegate_qt.h" #include "profile_qt.h" #include "qwebengineregisterprotocolhandlerrequest.h" #include "register_protocol_handler_request_controller_impl.h" @@ -63,8 +62,10 @@ #include "web_engine_settings.h" #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h" +#include "components/error_page/common/error.h" +#include "components/error_page/common/localized_error.h" #include "components/web_cache/browser/web_cache_manager.h" -#include "content/browser/frame_host/render_frame_host_impl.h" +#include "content/browser/renderer_host/render_frame_host_impl.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/browser_context.h" @@ -76,10 +77,8 @@ #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" -#include "content/public/common/favicon_url.h" #include "content/public/common/frame_navigate_params.h" #include "content/public/common/url_constants.h" -#include "content/public/common/web_preferences.h" #include "net/base/data_url.h" #include "net/base/url_util.h" @@ -106,7 +105,6 @@ WebContentsDelegateQt::WebContentsDelegateQt(content::WebContents *webContents, : m_viewClient(adapterClient) , m_faviconManager(new FaviconManager(webContents, adapterClient)) , m_findTextHelper(new FindTextHelper(webContents, adapterClient)) - , m_lastLoadProgress(-1) , m_loadingState(determineLoadingState(webContents)) , m_didStartLoadingSeen(m_loadingState == LoadingState::Loading) , m_frameFocusedObserver(adapterClient) @@ -128,7 +126,7 @@ content::WebContents *WebContentsDelegateQt::OpenURLFromTab(content::WebContents content::SiteInstance *target_site_instance = params.source_site_instance.get(); content::Referrer referrer = params.referrer; if (params.disposition != WindowOpenDisposition::CURRENT_TAB) { - QSharedPointer<WebContentsAdapter> targetAdapter = createWindow(0, params.disposition, gfx::Rect(), params.user_gesture); + QSharedPointer<WebContentsAdapter> targetAdapter = createWindow(nullptr, params.disposition, gfx::Rect(), toQt(params.url), params.user_gesture); if (targetAdapter) { if (targetAdapter->profile() != source->GetBrowserContext()) { target_site_instance = nullptr; @@ -137,6 +135,8 @@ content::WebContents *WebContentsDelegateQt::OpenURLFromTab(content::WebContents if (!targetAdapter->isInitialized()) targetAdapter->initialize(target_site_instance); target = targetAdapter->webContents(); + } else { + return target; } } Q_ASSERT(target); @@ -157,7 +157,7 @@ content::WebContents *WebContentsDelegateQt::OpenURLFromTab(content::WebContents load_url_params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE; load_url_params.href_translate = params.href_translate; load_url_params.reload_type = params.reload_type; - if (params.uses_post) { + if (params.post_data) { load_url_params.load_type = content::NavigationController::LOAD_TYPE_HTTP_POST; load_url_params.post_data = params.post_data; } @@ -189,58 +189,61 @@ static bool shouldUseActualURL(content::NavigationEntry *entry) void WebContentsDelegateQt::NavigationStateChanged(content::WebContents* source, content::InvalidateTypes changed_flags) { - if (changed_flags & content::INVALIDATE_TYPE_URL) { - content::NavigationEntry *entry = source->GetController().GetVisibleEntry(); - - QUrl newUrl; - if (source->GetVisibleURL().SchemeIs(content::kViewSourceScheme)) { - Q_ASSERT(entry); - GURL url = entry->GetURL(); - - // Strip user name, password and reference section from view-source URLs - if (url.has_password() || url.has_username() || url.has_ref()) { - GURL strippedUrl = net::SimplifyUrlForRequest(entry->GetURL()); - newUrl = QUrl(QString("%1:%2").arg(content::kViewSourceScheme, QString::fromStdString(strippedUrl.spec()))); - } - } - - // If there is a visible entry there are special cases when we dont wan't to use the actual URL - if (entry && newUrl.isEmpty()) - newUrl = shouldUseActualURL(entry) ? toQt(entry->GetURL()) : toQt(entry->GetVirtualURL()); - - if (m_url != newUrl) { - m_url = newUrl; - m_viewClient->urlChanged(m_url); - } + if (changed_flags & content::INVALIDATE_TYPE_URL && !m_pendingUrlUpdate) { + m_pendingUrlUpdate = true; + base::WeakPtr<WebContentsDelegateQt> delegate = AsWeakPtr(); + QTimer::singleShot(0, [delegate, this](){ if (delegate) m_viewClient->urlChanged();}); } if (changed_flags & content::INVALIDATE_TYPE_TITLE) { QString newTitle = toQt(source->GetTitle()); if (m_title != newTitle) { m_title = newTitle; - m_viewClient->titleChanged(m_title); + QTimer::singleShot(0, [delegate = AsWeakPtr(), title = newTitle] () { + if (delegate) + delegate->adapterClient()->titleChanged(title); + }); } } - // NavigationStateChanged gets called with INVALIDATE_TYPE_TAB by AudioStateProvider::Notify, - // whenever an audio sound gets played or stopped, this is the only way to actually figure out - // if there was a recently played audio sound. // Make sure to only emit the signal when loading isn't in progress, because it causes multiple // false signals to be emitted. - if ((changed_flags & content::INVALIDATE_TYPE_TAB) && !(changed_flags & content::INVALIDATE_TYPE_LOAD)) { + if ((changed_flags & content::INVALIDATE_TYPE_AUDIO) && !(changed_flags & content::INVALIDATE_TYPE_LOAD)) { m_viewClient->recentlyAudibleChanged(source->IsCurrentlyAudible()); } } -void WebContentsDelegateQt::AddNewContents(content::WebContents* source, std::unique_ptr<content::WebContents> new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture, bool* was_blocked) +QUrl WebContentsDelegateQt::url(content::WebContents* source) const { + + content::NavigationEntry *entry = source->GetController().GetVisibleEntry(); + QUrl newUrl; + if (entry) { + GURL url = entry->GetURL(); + // Strip user name, password and reference section from view-source URLs + if (source->GetVisibleURL().SchemeIs(content::kViewSourceScheme) && + (url.has_password() || url.has_username() || url.has_ref())) { + GURL strippedUrl = net::SimplifyUrlForRequest(url); + newUrl = QUrl(QString("%1:%2").arg(content::kViewSourceScheme, QString::fromStdString(strippedUrl.spec()))); + } + // If there is a visible entry there are special cases when we dont wan't to use the actual URL + if (newUrl.isEmpty()) + newUrl = shouldUseActualURL(entry) ? toQt(url) : toQt(entry->GetVirtualURL()); + } + m_pendingUrlUpdate = false; + return newUrl; +} +void WebContentsDelegateQt::AddNewContents(content::WebContents* source, std::unique_ptr<content::WebContents> new_contents, const GURL &target_url, + WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture, bool* was_blocked) { Q_UNUSED(source) - QSharedPointer<WebContentsAdapter> newAdapter = createWindow(std::move(new_contents), disposition, initial_pos, user_gesture); + QSharedPointer<WebContentsAdapter> newAdapter = createWindow(std::move(new_contents), disposition, initial_pos, toQt(target_url), user_gesture); // Chromium can forget to pass user-agent override settings to new windows (see QTBUG-61774 and QTBUG-76249), // so set it here. Note the actual value doesn't really matter here. Only the second value does, but we try // to give the correct user-agent anyway. if (newAdapter) - newAdapter->webContents()->SetUserAgentOverride(newAdapter->profileAdapter()->httpUserAgent().toStdString(), true); + newAdapter->webContents()->SetUserAgentOverride( + blink::UserAgentOverride::UserAgentOnly(newAdapter->profileAdapter()->httpUserAgent().toStdString()), + true); if (newAdapter && !newAdapter->isInitialized()) newAdapter->loadDefault(); if (was_blocked) @@ -249,19 +252,21 @@ void WebContentsDelegateQt::AddNewContents(content::WebContents* source, std::un void WebContentsDelegateQt::CloseContents(content::WebContents *source) { - m_viewClient->close(); GetJavaScriptDialogManager(source)->CancelDialogs(source, /* whatever?: */false); + // Must be the last call because close() might trigger the destruction of this object. + m_viewClient->close(); } -void WebContentsDelegateQt::LoadProgressChanged(content::WebContents */*source*/, double progress) +void WebContentsDelegateQt::LoadProgressChanged(double progress) { - if (!m_loadingErrorFrameList.isEmpty()) + if (!m_loadingInfo.isLoading()) // suppress signals that aren't between loadStarted and loadFinished return; - if (m_lastLoadProgress < 0) // suppress signals that aren't between loadStarted and loadFinished - return; - m_lastLoadProgress = qMax(m_lastLoadProgress, qRound(progress * 100)); // ensure monotonicity - m_lastLoadProgress = qMin(m_lastLoadProgress, 100); - m_viewClient->loadProgressChanged(m_lastLoadProgress); + + int p = qMin(qRound(progress * 100), 100); + if (p > m_loadingInfo.progress) { // ensure strict monotonic increase + m_loadingInfo.progress = p; + m_viewClient->loadProgressChanged(p); + } } bool WebContentsDelegateQt::HandleKeyboardEvent(content::WebContents *, const content::NativeWebKeyboardEvent &event) @@ -279,11 +284,6 @@ void WebContentsDelegateQt::RenderFrameCreated(content::RenderFrameHost *render_ m_frameFocusedObserver.addNode(node); } -void WebContentsDelegateQt::RenderFrameDeleted(content::RenderFrameHost *render_frame_host) -{ - m_loadingErrorFrameList.removeOne(render_frame_host->GetRoutingID()); -} - void WebContentsDelegateQt::RenderProcessGone(base::TerminationStatus status) { // RenderProcessHost::FastShutdownIfPossible results in TERMINATION_STATUS_STILL_RUNNING @@ -313,6 +313,16 @@ void WebContentsDelegateQt::RenderFrameHostChanged(content::RenderFrameHost *old if (new_host) { content::FrameTreeNode *new_node = static_cast<content::RenderFrameHostImpl *>(new_host)->frame_tree_node(); m_frameFocusedObserver.addNode(new_node); + + // Is this a main frame? + if (new_host->GetFrameOwnerElementType() == blink::mojom::FrameOwnerElementType::kNone) { + content::RenderProcessHost *renderProcessHost = new_host->GetProcess(); + const base::Process &process = renderProcessHost->GetProcess(); + if (process.IsValid()) { + m_viewClient->renderProcessPidChanged(process.Pid()); + m_viewClient->zoomUpdateIsNeeded(); + } + } } } @@ -321,43 +331,65 @@ void WebContentsDelegateQt::RenderViewHostChanged(content::RenderViewHost *, con if (newHost && newHost->GetWidget() && newHost->GetWidget()->GetView()) { auto rwhv = static_cast<RenderWidgetHostViewQt *>(newHost->GetWidget()->GetView()); m_viewClient->widgetChanged(rwhv->delegate()); + m_viewClient->zoomUpdateIsNeeded(); } } -void WebContentsDelegateQt::EmitLoadStarted(const QUrl &url, bool isErrorPage) +void WebContentsDelegateQt::emitLoadStarted(bool isErrorPage) { - if (m_lastLoadProgress >= 0 && m_lastLoadProgress < 100) // already running + // only report first ever load start or separate one for error page only + if (!isErrorPage && m_loadingInfo.isLoading()) // already running return; - m_viewClient->loadStarted(url, isErrorPage); - m_viewClient->updateNavigationActions(); - m_viewClient->loadProgressChanged(0); - m_lastLoadProgress = 0; + + m_isDocumentEmpty = true; // reset to default which may only be overridden on actual resource load complete + if (!isErrorPage) { + m_loadingInfo.progress = 0; + m_viewClient->loadStarted(m_loadingInfo.url, false); + m_viewClient->updateNavigationActions(); + m_viewClient->loadProgressChanged(0); + } else { + m_viewClient->loadStarted(toQt(GURL(content::kUnreachableWebDataURL)), true); + } } void WebContentsDelegateQt::DidStartNavigation(content::NavigationHandle *navigation_handle) { - if (!navigation_handle->IsInMainFrame()) - return; + if (!webEngineSettings()->testAttribute(WebEngineSettings::ErrorPageEnabled)) + navigation_handle->SetSilentlyIgnoreErrors(); - // Error-pages are not reported as separate started navigations. - Q_ASSERT(!navigation_handle->IsErrorPage()); + if (!navigation_handle->IsInMainFrame() || navigation_handle->IsSameDocument()) + return; - m_loadingErrorFrameList.clear(); m_faviconManager->resetCandidates(); - EmitLoadStarted(toQt(navigation_handle->GetURL())); + + m_loadingInfo.url = toQt(navigation_handle->GetURL()); + // IsErrorPage is only set after navigation commit, so check it otherwise: error page shouldn't have navigation entry + bool isErrorPage = m_loadingInfo.triggersErrorPage && !navigation_handle->GetNavigationEntry(); + emitLoadStarted(isErrorPage); } -void WebContentsDelegateQt::EmitLoadFinished(bool success, const QUrl &url, bool isErrorPage, int errorCode, const QString &errorDescription) +void WebContentsDelegateQt::emitLoadFinished(bool isErrorPage) { - if (m_lastLoadProgress < 0) // not currently running + if (!m_loadingInfo.isLoading()) // not currently running return; - m_lastLoadProgress = -1; - m_viewClient->loadProgressChanged(100); - m_viewClient->loadFinished(success, url, isErrorPage, errorCode, errorDescription); - m_viewClient->updateNavigationActions(); + + Q_ASSERT(!isErrorPage || webEngineSettings()->testAttribute(WebEngineSettings::ErrorPageEnabled)); + Q_ASSERT((m_loadingInfo.triggersErrorPage && webEngineSettings()->testAttribute(WebEngineSettings::ErrorPageEnabled)) || !m_loadingInfo.triggersErrorPage); + + if (!isErrorPage) { + if (m_loadingInfo.progress < 100) { + m_loadingInfo.progress = 100; + m_viewClient->loadProgressChanged(100); + } + + m_viewClient->loadFinished(m_loadingInfo.success, m_loadingInfo.url, false, m_loadingInfo.errorCode, m_loadingInfo.errorDescription); + m_viewClient->updateNavigationActions(); + } else { + m_viewClient->loadFinished(false, toQt(GURL(content::kUnreachableWebDataURL)), true, 0, QString()); + } } -void WebContentsDelegateQt::EmitLoadCommitted() +void WebContentsDelegateQt::emitLoadCommitted() { m_findTextHelper->handleLoadCommitted(); m_viewClient->loadCommitted(); @@ -377,8 +409,9 @@ void WebContentsDelegateQt::DidFinishNavigation(content::NavigationHandle *navig profileAdapter->visitedLinksManager()->addUrl(url); } - EmitLoadCommitted(); + emitLoadCommitted(); } + // Success is reported by DidFinishLoad, but DidFailLoad is now dead code and needs to be handled below if (navigation_handle->GetNetErrorCode() == net::OK) return; @@ -391,13 +424,12 @@ void WebContentsDelegateQt::DidFinishNavigation(content::NavigationHandle *navig // The load will succede as an error-page load later, and we reported the original error above if (navigation_handle->IsErrorPage()) { // Now report we are starting to load an error-page. - m_loadingErrorFrameList.append(navigation_handle->GetRenderFrameHost()->GetRoutingID()); m_faviconManager->resetCandidates(); - EmitLoadStarted(toQt(GURL(content::kUnreachableWebDataURL)), true); + emitLoadStarted(true); // If it is already committed we will not see another DidFinishNavigation call or a DidFinishLoad call. if (navigation_handle->HasCommitted()) - EmitLoadCommitted(); + emitLoadCommitted(); } } @@ -439,15 +471,26 @@ void WebContentsDelegateQt::DidStopLoading() if (m_loadingState == LoadingState::Loading) setLoadingState(LoadingState::Loaded); + + emitLoadFinished(); + m_loadingInfo.clear(); } void WebContentsDelegateQt::didFailLoad(const QUrl &url, int errorCode, const QString &errorDescription) { m_viewClient->iconChanged(QUrl()); - EmitLoadFinished(false /* success */ , url, false /* isErrorPage */, errorCode, errorDescription); + bool errorPageEnabled = webEngineSettings()->testAttribute(WebEngineSettings::ErrorPageEnabled); + // Delay notifying failure until the error-page is done loading. + // Error-pages are not loaded on failures due to abort. + bool aborted = (errorCode == -3 /* ERR_ABORTED*/ ); + m_loadingInfo.success = false; + m_loadingInfo.url = url; + m_loadingInfo.errorCode = errorCode; + m_loadingInfo.errorDescription = errorDescription; + m_loadingInfo.triggersErrorPage = errorPageEnabled && !aborted; } -void WebContentsDelegateQt::DidFailLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url, int error_code, const base::string16& error_description) +void WebContentsDelegateQt::DidFailLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url, int error_code) { if (m_loadingState == LoadingState::Loading) setLoadingState(LoadingState::Loaded); @@ -458,13 +501,15 @@ void WebContentsDelegateQt::DidFailLoad(content::RenderFrameHost* render_frame_h if (validated_url.spec() == content::kUnreachableWebDataURL) { // error-pages should only ever fail due to abort: Q_ASSERT(error_code == -3 /* ERR_ABORTED */); - m_loadingErrorFrameList.removeOne(render_frame_host->GetRoutingID()); m_viewClient->iconChanged(QUrl()); - - EmitLoadFinished(false /* success */, toQt(validated_url), true /* isErrorPage */); + emitLoadFinished(/* isErrorPage = */true); return; } - + // Qt6: Consider getting rid of the error_description (Chromium already has) + base::string16 error_description; + error_description = error_page::LocalizedError::GetErrorDetails( + error_code <= 0 ? error_page::Error::kNetErrorDomain : error_page::Error::kHttpErrorDomain, + error_code, false, false); didFailLoad(toQt(validated_url), error_code, toQt(error_description)); } @@ -472,34 +517,39 @@ void WebContentsDelegateQt::DidFinishLoad(content::RenderFrameHost* render_frame { Q_ASSERT(validated_url.is_valid()); if (validated_url.spec() == content::kUnreachableWebDataURL) { - m_loadingErrorFrameList.removeOne(render_frame_host->GetRoutingID()); - m_viewClient->iconChanged(QUrl()); - // Trigger LoadFinished signal for main frame's error page only. - if (!render_frame_host->GetParent()) - EmitLoadFinished(true /* success */, toQt(validated_url), true /* isErrorPage */); + if (!render_frame_host->GetParent()) { + m_viewClient->iconChanged(QUrl()); + emitLoadFinished(/* isErrorPage = */true); + } return; } - if (render_frame_host->GetParent()) + if (render_frame_host->GetParent()) { + m_viewClient->updateNavigationActions(); return; + } if (!m_faviconManager->hasCandidate()) m_viewClient->iconChanged(QUrl()); content::NavigationEntry *entry = web_contents()->GetController().GetActiveEntry(); - int http_statuscode = 0; - if (entry) - http_statuscode = entry->GetHttpStatusCode(); - EmitLoadFinished(true /* success */ , toQt(validated_url), false /* isErrorPage */, http_statuscode); + int http_statuscode = entry ? entry->GetHttpStatusCode() : 0; + bool errorPageEnabled = webEngineSettings()->testAttribute(WebEngineSettings::ErrorPageEnabled); + bool triggersErrorPage = errorPageEnabled && (http_statuscode >= 400) && m_isDocumentEmpty; + + m_loadingInfo.success = http_statuscode < 400; + m_loadingInfo.url = toQt(validated_url); + m_loadingInfo.errorCode = http_statuscode; + m_loadingInfo.triggersErrorPage = triggersErrorPage; } -void WebContentsDelegateQt::DidUpdateFaviconURL(const std::vector<content::FaviconURL> &candidates) +void WebContentsDelegateQt::DidUpdateFaviconURL(content::RenderFrameHost *render_frame_host, const std::vector<blink::mojom::FaviconURLPtr> &candidates) { QList<FaviconInfo> faviconCandidates; faviconCandidates.reserve(static_cast<int>(candidates.size())); - for (const content::FaviconURL &candidate : candidates) { + for (const blink::mojom::FaviconURLPtr &candidate : candidates) { // Store invalid candidates too for later debugging via API faviconCandidates.append(toFaviconInfo(candidate)); } @@ -513,9 +563,8 @@ void WebContentsDelegateQt::DidUpdateFaviconURL(const std::vector<content::Favic void WebContentsDelegateQt::WebContentsCreated(content::WebContents * /*source_contents*/, int /*opener_render_process_id*/, int /*opener_render_frame_id*/, const std::string &/*frame_name*/, - const GURL &target_url, content::WebContents *newContents) + const GURL &/*target_url*/, content::WebContents *newContents) { - m_initialTargetUrl = toQt(target_url); if (auto *view = static_cast<content::WebContentsImpl *>(newContents)->GetView()) static_cast<WebContentsViewQt *>(view)->setFactoryClient(m_viewClient); } @@ -533,11 +582,11 @@ content::JavaScriptDialogManager *WebContentsDelegateQt::GetJavaScriptDialogMana return JavaScriptDialogManagerQt::GetInstance(); } -void WebContentsDelegateQt::EnterFullscreenModeForTab(content::WebContents *web_contents, const GURL& origin, const blink::WebFullscreenOptions &) +void WebContentsDelegateQt::EnterFullscreenModeForTab(content::RenderFrameHost *requesting_frame, const blink::mojom::FullscreenOptions &options) { - Q_UNUSED(web_contents); + Q_UNUSED(options); if (!m_viewClient->isFullScreenMode()) - m_viewClient->requestFullScreenMode(toQt(origin), true); + m_viewClient->requestFullScreenMode(toQt(requesting_frame->GetLastCommittedURL()), true); } void WebContentsDelegateQt::ExitFullscreenModeForTab(content::WebContents *web_contents) @@ -557,8 +606,10 @@ ASSERT_ENUMS_MATCH(FilePickerController::OpenMultiple, blink::mojom::FileChooser ASSERT_ENUMS_MATCH(FilePickerController::UploadFolder, blink::mojom::FileChooserParams::Mode::kUploadFolder) ASSERT_ENUMS_MATCH(FilePickerController::Save, blink::mojom::FileChooserParams::Mode::kSave) +extern FilePickerController *createFilePickerController(FilePickerController::FileChooserMode mode, scoped_refptr<content::FileSelectListener> listener, const QString &defaultFileName, const QStringList &acceptedMimeTypes, QObject *parent = nullptr); + void WebContentsDelegateQt::RunFileChooser(content::RenderFrameHost * /*frameHost*/, - std::unique_ptr<content::FileSelectListener> listener, + scoped_refptr<content::FileSelectListener> listener, const blink::mojom::FileChooserParams& params) { QStringList acceptedMimeTypes; @@ -566,8 +617,8 @@ void WebContentsDelegateQt::RunFileChooser(content::RenderFrameHost * /*frameHos for (std::vector<base::string16>::const_iterator it = params.accept_types.begin(); it < params.accept_types.end(); ++it) acceptedMimeTypes.append(toQt(*it)); - m_filePickerController.reset(new FilePickerController(static_cast<FilePickerController::FileChooserMode>(params.mode), - std::move(listener), toQt(params.default_file_name.value()), acceptedMimeTypes)); + m_filePickerController.reset(createFilePickerController(static_cast<FilePickerController::FileChooserMode>(params.mode), + listener, toQt(params.default_file_name.value()), acceptedMimeTypes)); // Defer the call to not block base::MessageLoop::RunTask with modal dialogs. QTimer::singleShot(0, [this] () { @@ -590,7 +641,7 @@ void WebContentsDelegateQt::FindReply(content::WebContents *source, int request_ void WebContentsDelegateQt::RequestMediaAccessPermission(content::WebContents *web_contents, const content::MediaStreamRequest &request, content::MediaResponseCallback callback) { - MediaCaptureDevicesDispatcher::GetInstance()->processMediaAccessRequest(m_viewClient, web_contents, request, std::move(callback)); + MediaCaptureDevicesDispatcher::GetInstance()->processMediaAccessRequest(web_contents, request, std::move(callback)); } void WebContentsDelegateQt::SetContentsBounds(content::WebContents *source, const gfx::Rect &bounds) @@ -640,24 +691,27 @@ void WebContentsDelegateQt::RequestToLockMouse(content::WebContents *web_content Q_UNUSED(user_gesture); if (last_unlocked_by_target) - web_contents->GotResponseToLockMouseRequest(true); + web_contents->GotResponseToLockMouseRequest(blink::mojom::PointerLockResult::kSuccess); else - m_viewClient->runMouseLockPermissionRequest(toQt(web_contents->GetVisibleURL())); + m_viewClient->runMouseLockPermissionRequest(toQt(web_contents->GetLastCommittedURL().GetOrigin())); } -void WebContentsDelegateQt::overrideWebPreferences(content::WebContents *webContents, content::WebPreferences *webPreferences) +void WebContentsDelegateQt::overrideWebPreferences(content::WebContents *webContents, blink::web_pref::WebPreferences *webPreferences) { m_viewClient->webEngineSettings()->overrideWebPreferences(webContents, webPreferences); } -QWeakPointer<WebContentsAdapter> WebContentsDelegateQt::createWindow(std::unique_ptr<content::WebContents> new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture) +QSharedPointer<WebContentsAdapter> +WebContentsDelegateQt::createWindow(std::unique_ptr<content::WebContents> new_contents, + WindowOpenDisposition disposition, const gfx::Rect &initial_pos, const QUrl &url, + bool user_gesture) { QSharedPointer<WebContentsAdapter> newAdapter = QSharedPointer<WebContentsAdapter>::create(std::move(new_contents)); - m_viewClient->adoptNewWindow(newAdapter, static_cast<WebContentsAdapterClient::WindowOpenDisposition>(disposition), user_gesture, toQt(initial_pos), m_initialTargetUrl); - - // If the client didn't reference the adapter, it will be deleted now, and the weak pointer zeroed. - return newAdapter; + return m_viewClient->adoptNewWindow( + std::move(newAdapter), + static_cast<WebContentsAdapterClient::WindowOpenDisposition>(disposition), user_gesture, + toQt(initial_pos), url); } void WebContentsDelegateQt::allowCertificateError(const QSharedPointer<CertificateErrorController> &errorController) @@ -670,14 +724,9 @@ void WebContentsDelegateQt::selectClientCert(const QSharedPointer<ClientCertSele m_viewClient->selectClientCert(selectController); } -void WebContentsDelegateQt::requestGeolocationPermission(const QUrl &requestingOrigin) +void WebContentsDelegateQt::requestFeaturePermission(ProfileAdapter::PermissionType feature, const QUrl &requestingOrigin) { - m_viewClient->runGeolocationPermissionRequest(requestingOrigin); -} - -void WebContentsDelegateQt::requestUserNotificationPermission(const QUrl &requestingOrigin) -{ - m_viewClient->runUserNotificationPermissionRequest(requestingOrigin); + m_viewClient->runFeaturePermissionRequest(feature, requestingOrigin); } extern WebContentsAdapterClient::NavigationType pageTransitionToNavigationType(ui::PageTransition transition); @@ -750,9 +799,9 @@ bool WebContentsDelegateQt::CheckMediaAccessPermission(content::RenderFrameHost } } -void WebContentsDelegateQt::RegisterProtocolHandler(content::WebContents *webContents, const std::string &protocol, const GURL &url, bool) +void WebContentsDelegateQt::RegisterProtocolHandler(content::RenderFrameHost *frameHost, const std::string &protocol, const GURL &url, bool) { - content::BrowserContext *context = webContents->GetBrowserContext(); + content::BrowserContext *context = frameHost->GetBrowserContext(); if (context->IsOffTheRecord()) return; @@ -765,13 +814,13 @@ void WebContentsDelegateQt::RegisterProtocolHandler(content::WebContents *webCon return; QWebEngineRegisterProtocolHandlerRequest request( - QSharedPointer<RegisterProtocolHandlerRequestControllerImpl>::create(webContents, handler)); + QSharedPointer<RegisterProtocolHandlerRequestControllerImpl>::create(content::WebContents::FromRenderFrameHost(frameHost), handler)); m_viewClient->runRegisterProtocolHandlerRequest(std::move(request)); } -void WebContentsDelegateQt::UnregisterProtocolHandler(content::WebContents *webContents, const std::string &protocol, const GURL &url, bool) +void WebContentsDelegateQt::UnregisterProtocolHandler(content::RenderFrameHost *frameHost, const std::string &protocol, const GURL &url, bool) { - content::BrowserContext* context = webContents->GetBrowserContext(); + content::BrowserContext* context = frameHost->GetBrowserContext(); if (context->IsOffTheRecord()) return; @@ -789,6 +838,36 @@ bool WebContentsDelegateQt::TakeFocus(content::WebContents *source, bool reverse return m_viewClient->passOnFocus(reverse); } +void WebContentsDelegateQt::ContentsZoomChange(bool zoom_in) +{ + WebContentsAdapter *adapter = webContentsAdapter(); + if (zoom_in) + adapter->setZoomFactor(adapter->currentZoomFactor() + 0.1f); + else + adapter->setZoomFactor(adapter->currentZoomFactor() - 0.1f); +} + +bool WebContentsDelegateQt::ShouldNavigateOnBackForwardMouseButtons() +{ +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + return false; +#else + return true; +#endif +} + +void WebContentsDelegateQt::ResourceLoadComplete(content::RenderFrameHost* render_frame_host, + const content::GlobalRequestID& request_id, + const blink::mojom::ResourceLoadInfo& resource_load_info) +{ + Q_UNUSED(render_frame_host); + Q_UNUSED(request_id); + + if (resource_load_info.request_destination == network::mojom::RequestDestination::kDocument) { + m_isDocumentEmpty = (resource_load_info.raw_body_bytes == 0); + } +} + FaviconManager *WebContentsDelegateQt::faviconManager() { return m_faviconManager.data(); @@ -810,7 +889,6 @@ WebContentsAdapter *WebContentsDelegateQt::webContentsAdapter() const void WebContentsDelegateQt::copyStateFrom(WebContentsDelegateQt *source) { - m_url = source->m_url; m_title = source->m_title; NavigationStateChanged(web_contents(), content::INVALIDATE_TYPE_URL); m_faviconManager->copyStateFrom(source->m_faviconManager.data()); diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h index ba8c6b5a1..50027b6a8 100644 --- a/src/core/web_contents_delegate_qt.h +++ b/src/core/web_contents_delegate_qt.h @@ -40,7 +40,7 @@ #ifndef WEB_CONTENTS_DELEGATE_QT_H #define WEB_CONTENTS_DELEGATE_QT_H -#include "content/browser/frame_host/frame_tree_node.h" +#include "content/browser/renderer_host/frame_tree_node.h" #include "content/public/browser/media_capture_devices.h" #include "content/public/browser/web_contents_delegate.h" #include "content/public/browser/web_contents_observer.h" @@ -58,12 +58,17 @@ QT_FORWARD_DECLARE_CLASS(CertificateErrorController) QT_FORWARD_DECLARE_CLASS(ClientCertSelectController) +namespace blink { + namespace web_pref { + struct WebPreferences; + } +} + namespace content { class ColorChooser; class SiteInstance; class JavaScriptDialogManager; class WebContents; - struct WebPreferences; struct ColorSuggestion; } @@ -114,25 +119,26 @@ public: WebContentsDelegateQt(content::WebContents*, WebContentsAdapterClient *adapterClient); ~WebContentsDelegateQt(); - QUrl url() const { return m_url; } + QUrl url(content::WebContents *source) const; QString title() const { return m_title; } // WebContentsDelegate overrides content::WebContents *OpenURLFromTab(content::WebContents *source, const content::OpenURLParams ¶ms) override; void NavigationStateChanged(content::WebContents* source, content::InvalidateTypes changed_flags) override; - void AddNewContents(content::WebContents *source, std::unique_ptr<content::WebContents> new_contents, WindowOpenDisposition disposition, const gfx::Rect &initial_pos, bool user_gesture, bool *was_blocked) override; + void AddNewContents(content::WebContents *source, std::unique_ptr<content::WebContents> new_contents, const GURL &target_url, + WindowOpenDisposition disposition, const gfx::Rect &initial_pos, bool user_gesture, bool *was_blocked) override; void CloseContents(content::WebContents *source) override; - void LoadProgressChanged(content::WebContents* source, double progress) override; + void LoadProgressChanged(double progress) override; bool HandleKeyboardEvent(content::WebContents *source, const content::NativeWebKeyboardEvent &event) override; content::ColorChooser* OpenColorChooser(content::WebContents *source, SkColor color, const std::vector<blink::mojom::ColorSuggestionPtr> &suggestions) override; void WebContentsCreated(content::WebContents *source_contents, int opener_render_process_id, int opener_render_frame_id, const std::string &frame_name, const GURL &target_url, content::WebContents *new_contents) override; content::JavaScriptDialogManager *GetJavaScriptDialogManager(content::WebContents *source) override; - void EnterFullscreenModeForTab(content::WebContents *web_contents, const GURL &origin, const blink::WebFullscreenOptions &) override; + void EnterFullscreenModeForTab(content::RenderFrameHost *requesting_frame, const blink::mojom::FullscreenOptions &options) override; void ExitFullscreenModeForTab(content::WebContents*) override; bool IsFullscreenForTabOrPending(const content::WebContents* web_contents) override; void RunFileChooser(content::RenderFrameHost* render_frame_host, - std::unique_ptr<content::FileSelectListener> listener, + scoped_refptr<content::FileSelectListener> listener, const blink::mojom::FileChooserParams& params) override; bool DidAddMessageToConsole(content::WebContents *source, blink::mojom::ConsoleMessageLevel log_level, const base::string16 &message, int32_t line_no, const base::string16 &source_id) override; @@ -145,13 +151,13 @@ public: void RequestToLockMouse(content::WebContents *web_contents, bool user_gesture, bool last_unlocked_by_target) override; void BeforeUnloadFired(content::WebContents* tab, bool proceed, bool* proceed_to_fire_unload) override; bool CheckMediaAccessPermission(content::RenderFrameHost* render_frame_host, const GURL& security_origin, blink::mojom::MediaStreamType type) override; - void RegisterProtocolHandler(content::WebContents* web_contents, const std::string& protocol, const GURL& url, bool user_gesture) override; - void UnregisterProtocolHandler(content::WebContents* web_contents, const std::string& protocol, const GURL& url, bool user_gesture) override; + void RegisterProtocolHandler(content::RenderFrameHost* frame_host, const std::string& protocol, const GURL& url, bool user_gesture) override; + void UnregisterProtocolHandler(content::RenderFrameHost* frame_host, const std::string& protocol, const GURL& url, bool user_gesture) override; bool TakeFocus(content::WebContents *source, bool reverse) override; + void ContentsZoomChange(bool zoom_in) override; // WebContentsObserver overrides void RenderFrameCreated(content::RenderFrameHost *render_frame_host) override; - void RenderFrameDeleted(content::RenderFrameHost *render_frame_host) override; void RenderProcessGone(base::TerminationStatus status) override; void RenderFrameHostChanged(content::RenderFrameHost *old_host, content::RenderFrameHost *new_host) override; void RenderViewHostChanged(content::RenderViewHost *old_host, content::RenderViewHost *new_host) override; @@ -160,20 +166,23 @@ public: void DidStartLoading() override; void DidReceiveResponse() override; void DidStopLoading() override; - void DidFailLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url, int error_code, const base::string16& error_description) override; + void DidFailLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url, int error_code) override; void DidFinishLoad(content::RenderFrameHost *render_frame_host, const GURL &validated_url) override; void BeforeUnloadFired(bool proceed, const base::TimeTicks& proceed_time) override; - void DidUpdateFaviconURL(const std::vector<content::FaviconURL> &candidates) override; + void DidUpdateFaviconURL(content::RenderFrameHost *render_frame_host, const std::vector<blink::mojom::FaviconURLPtr> &candidates) override; void OnVisibilityChanged(content::Visibility visibility) override; void DidFirstVisuallyNonEmptyPaint() override; void ActivateContents(content::WebContents* contents) override; + bool ShouldNavigateOnBackForwardMouseButtons() override; + void ResourceLoadComplete(content::RenderFrameHost* render_frame_host, + const content::GlobalRequestID& request_id, + const blink::mojom::ResourceLoadInfo& resource_load_info) override; void didFailLoad(const QUrl &url, int errorCode, const QString &errorDescription); - void overrideWebPreferences(content::WebContents *, content::WebPreferences*); + void overrideWebPreferences(content::WebContents *, blink::web_pref::WebPreferences*); void allowCertificateError(const QSharedPointer<CertificateErrorController> &); void selectClientCert(const QSharedPointer<ClientCertSelectController> &); - void requestGeolocationPermission(const QUrl &requestingOrigin); - void requestUserNotificationPermission(const QUrl &requestingOrigin); + void requestFeaturePermission(ProfileAdapter::PermissionType feature, const QUrl &requestingOrigin); void launchExternalURL(const QUrl &url, ui::PageTransition page_transition, bool is_main_frame, bool has_user_gesture); FaviconManager *faviconManager(); FindTextHelper *findTextHelper(); @@ -201,10 +210,14 @@ public: base::WeakPtr<WebContentsDelegateQt> AsWeakPtr() { return m_weakPtrFactory.GetWeakPtr(); } private: - QWeakPointer<WebContentsAdapter> createWindow(std::unique_ptr<content::WebContents> new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture); - void EmitLoadStarted(const QUrl &url, bool isErrorPage = false); - void EmitLoadFinished(bool success, const QUrl &url, bool isErrorPage = false, int errorCode = 0, const QString &errorDescription = QString()); - void EmitLoadCommitted(); + QSharedPointer<WebContentsAdapter> + createWindow(std::unique_ptr<content::WebContents> new_contents, + WindowOpenDisposition disposition, const gfx::Rect &initial_pos, + const QUrl &url, + bool user_gesture); + void emitLoadStarted(bool isErrorPage = false); + void emitLoadFinished(bool isErrorPage = false); + void emitLoadCommitted(); LoadingState determineLoadingState(content::WebContents *contents); void setLoadingState(LoadingState state); @@ -212,24 +225,33 @@ private: int &streamCount(blink::mojom::MediaStreamType type); WebContentsAdapterClient *m_viewClient; - QVector<int64_t> m_loadingErrorFrameList; QScopedPointer<FaviconManager> m_faviconManager; QScopedPointer<FindTextHelper> m_findTextHelper; SavePageInfo m_savePageInfo; QSharedPointer<FilePickerController> m_filePickerController; - QUrl m_initialTargetUrl; - int m_lastLoadProgress; LoadingState m_loadingState; bool m_didStartLoadingSeen; FrameFocusedObserver m_frameFocusedObserver; - QUrl m_url; QString m_title; int m_audioStreamCount = 0; int m_videoStreamCount = 0; int m_mirroringStreamCount = 0; int m_desktopStreamCount = 0; - + mutable bool m_pendingUrlUpdate = false; + + struct LoadingInfo { + bool success = false; + int progress = -1; + bool isLoading() const { return progress >= 0; } + QUrl url; + int errorCode = 0; + QString errorDescription; + bool triggersErrorPage = false; + void clear() { *this = LoadingInfo(); } + } m_loadingInfo; + + bool m_isDocumentEmpty = true; base::WeakPtrFactory<WebContentsDelegateQt> m_weakPtrFactory { this }; }; diff --git a/src/core/web_contents_view_qt.cpp b/src/core/web_contents_view_qt.cpp index e50835f74..900c53829 100644 --- a/src/core/web_contents_view_qt.cpp +++ b/src/core/web_contents_view_qt.cpp @@ -46,7 +46,6 @@ #include "render_widget_host_view_qt.h" #include "touch_selection_controller_client_qt.h" #include "type_conversion.h" -#include "web_contents_adapter_client.h" #include "web_contents_adapter.h" #include "web_engine_context.h" #include "web_contents_delegate_qt.h" @@ -55,14 +54,23 @@ #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" +#include "content/public/browser/context_menu_params.h" #include "content/public/browser/web_contents_delegate.h" -#include "content/public/common/context_menu_params.h" +#include "third_party/blink/public/common/context_menu_data/edit_flags.h" +#include "third_party/blink/public/common/context_menu_data/media_type.h" #include "ui/gfx/image/image_skia.h" #include <QtGui/qpixmap.h> namespace QtWebEngineCore { +WebContentsViewQt::WebContentsViewQt(content::WebContents *webContents) + : m_webContents(webContents) + , m_client(nullptr) + , m_factoryClient(nullptr) +{ +} + void WebContentsViewQt::setFactoryClient(WebContentsAdapterClient* client) { if (m_factoryClient) @@ -87,7 +95,7 @@ void WebContentsViewQt::setClient(WebContentsAdapterClient* client) } } -content::RenderWidgetHostViewBase* WebContentsViewQt::CreateViewForWidget(content::RenderWidgetHost* render_widget_host, bool is_guest_view_hack) +content::RenderWidgetHostViewBase* WebContentsViewQt::CreateViewForWidget(content::RenderWidgetHost *render_widget_host) { RenderWidgetHostViewQt *view = new RenderWidgetHostViewQt(render_widget_host); @@ -111,7 +119,7 @@ content::RenderWidgetHostViewBase* WebContentsViewQt::CreateViewForChildWidget(c return view; } -void WebContentsViewQt::CreateView(const gfx::Size& initial_size, gfx::NativeView context) +void WebContentsViewQt::CreateView(gfx::NativeView context) { } @@ -120,12 +128,13 @@ gfx::NativeView WebContentsViewQt::GetNativeView() const return nullptr; } -void WebContentsViewQt::GetContainerBounds(gfx::Rect* out) const +gfx::Rect WebContentsViewQt::GetContainerBounds() const { if (m_client) { const QRectF r(m_client->viewportRect()); - *out = gfx::Rect(r.x(), r.y(), r.width(), r.height()); + return gfx::Rect(r.x(), r.y(), r.width(), r.height()); } + return gfx::Rect(); } void WebContentsViewQt::Focus() @@ -145,10 +154,6 @@ void WebContentsViewQt::SetInitialFocus() void WebContentsViewQt::FocusThroughTabTraversal(bool reverse) { content::WebContentsImpl *web_contents = static_cast<content::WebContentsImpl*>(m_webContents); - if (web_contents->ShowingInterstitialPage()) { - web_contents->GetInterstitialPage()->FocusThroughTabTraversal(reverse); - return; - } content::RenderWidgetHostView *fullscreen_view = web_contents->GetFullscreenRenderWidgetHostView(); if (fullscreen_view) { fullscreen_view->Focus(); @@ -158,13 +163,13 @@ void WebContentsViewQt::FocusThroughTabTraversal(bool reverse) } -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypeNone, blink::WebContextMenuData::kMediaTypeNone) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypeImage, blink::WebContextMenuData::kMediaTypeImage) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypeVideo, blink::WebContextMenuData::kMediaTypeVideo) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypeAudio, blink::WebContextMenuData::kMediaTypeAudio) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypeCanvas, blink::WebContextMenuData::kMediaTypeCanvas) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypeFile, blink::WebContextMenuData::kMediaTypeFile) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypePlugin, blink::WebContextMenuData::kMediaTypePlugin) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypeNone, blink::ContextMenuDataMediaType::kNone) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypeImage, blink::ContextMenuDataMediaType::kImage) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypeVideo, blink::ContextMenuDataMediaType::kVideo) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypeAudio, blink::ContextMenuDataMediaType::kAudio) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypeCanvas, blink::ContextMenuDataMediaType::kCanvas) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypeFile, blink::ContextMenuDataMediaType::kFile) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypePlugin, blink::ContextMenuDataMediaType::kPlugin) ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaNone, blink::WebContextMenuData::kMediaNone) ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaInError, blink::WebContextMenuData::kMediaInError) @@ -178,33 +183,33 @@ ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaControls, blink::WebContextMen ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaCanPrint, blink::WebContextMenuData::kMediaCanPrint) ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaCanRotate, blink::WebContextMenuData::kMediaCanRotate) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::CanDoNone, blink::WebContextMenuData::kCanDoNone) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::CanUndo, blink::WebContextMenuData::kCanUndo) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::CanRedo, blink::WebContextMenuData::kCanRedo) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::CanCut, blink::WebContextMenuData::kCanCut) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::CanCopy, blink::WebContextMenuData::kCanCopy) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::CanPaste, blink::WebContextMenuData::kCanPaste) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::CanDelete, blink::WebContextMenuData::kCanDelete) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::CanSelectAll, blink::WebContextMenuData::kCanSelectAll) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::CanTranslate, blink::WebContextMenuData::kCanTranslate) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::CanEditRichly, blink::WebContextMenuData::kCanEditRichly) - -static inline WebEngineContextMenuData fromParams(const content::ContextMenuParams ¶ms) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::CanDoNone, blink::kCanDoNone) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::CanUndo, blink::kCanUndo) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::CanRedo, blink::kCanRedo) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::CanCut, blink::kCanCut) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::CanCopy, blink::kCanCopy) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::CanPaste, blink::kCanPaste) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::CanDelete, blink::kCanDelete) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::CanSelectAll, blink::kCanSelectAll) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::CanTranslate, blink::kCanTranslate) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::CanEditRichly, blink::kCanEditRichly) + +WebEngineContextMenuData WebContentsViewQt::buildContextMenuData(const content::ContextMenuParams ¶ms) { WebEngineContextMenuData ret; ret.setPosition(QPoint(params.x, params.y)); ret.setLinkUrl(toQt(params.link_url)); - ret.setLinkText(toQt(params.link_text.data())); - ret.setAltText(toQt(params.alt_text.data())); - ret.setTitleText(toQt(params.title_text.data())); + ret.setLinkText(toQt(params.link_text)); + ret.setAltText(toQt(params.alt_text)); + ret.setTitleText(toQt(params.title_text)); ret.setUnfilteredLinkUrl(toQt(params.unfiltered_link_url)); - ret.setSelectedText(toQt(params.selection_text.data())); + ret.setSelectedText(toQt(params.selection_text)); ret.setMediaUrl(toQt(params.src_url)); ret.setMediaType((WebEngineContextMenuData::MediaType)params.media_type); ret.setHasImageContent(params.has_image_contents); ret.setMediaFlags((WebEngineContextMenuData::MediaFlags)params.media_flags); ret.setEditFlags((WebEngineContextMenuData::EditFlags)params.edit_flags); - ret.setSuggestedFileName(toQt(params.suggested_filename.data())); + ret.setSuggestedFileName(toQt(params.suggested_filename)); ret.setIsEditable(params.is_editable); #if QT_CONFIG(webengine_spellchecker) ret.setMisspelledWord(toQt(params.misspelled_word)); @@ -223,7 +228,7 @@ void WebContentsViewQt::ShowContextMenu(content::RenderFrameHost *, const conten return; } - WebEngineContextMenuData contextMenuData(fromParams(params)); + WebEngineContextMenuData contextMenuData(buildContextMenuData(params)); #if QT_CONFIG(webengine_spellchecker) // Do not use params.spellcheck_enabled, since it is never // correctly initialized for chrome asynchronous spellchecking. @@ -237,23 +242,23 @@ void WebContentsViewQt::ShowContextMenu(content::RenderFrameHost *, const conten m_client->contextMenuRequested(contextMenuData); } -Qt::DropActions toQtDropActions(blink::WebDragOperationsMask ops) +static Qt::DropActions toQtDropActions(blink::DragOperationsMask ops) { Qt::DropActions result; - if (ops & blink::kWebDragOperationCopy) + if (ops & blink::kDragOperationCopy) result |= Qt::CopyAction; - if (ops & blink::kWebDragOperationLink) + if (ops & blink::kDragOperationLink) result |= Qt::LinkAction; - if (ops & blink::kWebDragOperationMove || ops & blink::kWebDragOperationDelete) + if (ops & blink::kDragOperationMove || ops & blink::kDragOperationDelete) result |= Qt::MoveAction; return result; } void WebContentsViewQt::StartDragging(const content::DropData &drop_data, - blink::WebDragOperationsMask allowed_ops, + blink::DragOperationsMask allowed_ops, const gfx::ImageSkia &image, const gfx::Vector2d &image_offset, - const content::DragEventSourceInfo &event_info, + const blink::mojom::DragEventSourceInfo &event_info, content::RenderWidgetHostImpl* source_rwh) { #if QT_CONFIG(draganddrop) @@ -277,7 +282,7 @@ void WebContentsViewQt::StartDragging(const content::DropData &drop_data, #endif // QT_CONFIG(draganddrop) } -void WebContentsViewQt::UpdateDragCursor(blink::WebDragOperation dragOperation) +void WebContentsViewQt::UpdateDragCursor(blink::DragOperation dragOperation) { #if QT_CONFIG(draganddrop) m_client->webContentsAdapter()->updateDragAction(dragOperation); diff --git a/src/core/web_contents_view_qt.h b/src/core/web_contents_view_qt.h index 978a2ce2e..da0c5d20c 100644 --- a/src/core/web_contents_view_qt.h +++ b/src/core/web_contents_view_qt.h @@ -44,6 +44,7 @@ #include "content/browser/web_contents/web_contents_view.h" #include "api/qtwebenginecoreglobal_p.h" +#include "web_contents_adapter_client.h" namespace content { class WebContents; @@ -59,27 +60,21 @@ class WebContentsViewQt public: static inline WebContentsViewQt *from(WebContentsView *view) { return static_cast<WebContentsViewQt*>(view); } - WebContentsViewQt(content::WebContents* webContents) - : m_webContents(webContents) - , m_client(nullptr) - , m_factoryClient(nullptr) - { } + WebContentsViewQt(content::WebContents *webContents); void setFactoryClient(WebContentsAdapterClient* client); void setClient(WebContentsAdapterClient* client); WebContentsAdapterClient *client() { return m_client; } // content::WebContentsView overrides: - content::RenderWidgetHostViewBase *CreateViewForWidget(content::RenderWidgetHost* render_widget_host, bool is_guest_view_hack) override; + content::RenderWidgetHostViewBase *CreateViewForWidget(content::RenderWidgetHost *render_widget_host) override; - void CreateView(const gfx::Size& initial_size, gfx::NativeView context) override; + void CreateView(gfx::NativeView context) override; content::RenderWidgetHostViewBase *CreateViewForChildWidget(content::RenderWidgetHost* render_widget_host) override; void SetPageTitle(const base::string16& title) override { } - void RenderViewCreated(content::RenderViewHost* host) override { } - void RenderViewReady() override { } void RenderViewHostChanged(content::RenderViewHost*, content::RenderViewHost*) override { } @@ -92,9 +87,7 @@ public: gfx::NativeWindow GetTopLevelNativeWindow() const override { return nullptr; } - void GetContainerBounds(gfx::Rect* out) const override; - - void SizeContents(const gfx::Size& size) override { } + gfx::Rect GetContainerBounds() const override; void Focus() override; @@ -110,17 +103,17 @@ public: void FocusThroughTabTraversal(bool reverse) override; -#if defined(OS_MACOSX) +#if defined(OS_MAC) bool CloseTabAfterEventTrackingIfNeeded() override { QT_NOT_YET_IMPLEMENTED return false; } -#endif // defined(OS_MACOSX) +#endif // defined(OS_MAC) // content::RenderViewHostDelegateView overrides: - void StartDragging(const content::DropData& drop_data, blink::WebDragOperationsMask allowed_ops, + void StartDragging(const content::DropData& drop_data, blink::DragOperationsMask allowed_ops, const gfx::ImageSkia& image, const gfx::Vector2d& image_offset, - const content::DragEventSourceInfo& event_info, - content::RenderWidgetHostImpl* source_rwh) override; + const blink::mojom::DragEventSourceInfo &event_info, + content::RenderWidgetHostImpl *source_rwh) override; - void UpdateDragCursor(blink::WebDragOperation dragOperation) override; + void UpdateDragCursor(blink::DragOperation dragOperation) override; void ShowContextMenu(content::RenderFrameHost *, const content::ContextMenuParams ¶ms) override; @@ -128,6 +121,8 @@ public: void LostFocus(content::RenderWidgetHostImpl *render_widget_host) override; void TakeFocus(bool reverse) override; + static WebEngineContextMenuData buildContextMenuData(const content::ContextMenuParams ¶ms); + private: content::WebContents *m_webContents; WebContentsAdapterClient *m_client; diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 6e805fa67..184f78c3b 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -44,14 +44,24 @@ #include "base/base_switches.h" #include "base/command_line.h" #include "base/files/file_path.h" +#include "base/power_monitor/power_monitor.h" +#include "base/power_monitor/power_monitor_device_source.h" #include "base/run_loop.h" #include "base/task/post_task.h" #include "base/task/sequence_manager/thread_controller_with_message_pump_impl.h" +#include "base/task/thread_pool/thread_pool_instance.h" #include "base/threading/thread_restrictions.h" #include "cc/base/switches.h" +#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) +#include "chrome/browser/media/webrtc/webrtc_log_uploader.h" +#endif +#include "chrome/common/chrome_switches.h" +#include "content/gpu/gpu_child_thread.h" +#include "content/browser/compositor/surface_utils.h" +#include "content/browser/compositor/viz_process_transport_factory.h" +#include "components/viz/host/host_frame_sink_manager.h" #if QT_CONFIG(webengine_printing_and_pdf) #include "chrome/browser/printing/print_job_manager.h" -#include "components/printing/browser/features.h" #endif #include "components/discardable_memory/service/discardable_shared_memory_manager.h" #include "components/viz/common/features.h" @@ -81,12 +91,15 @@ #include "mojo/core/embedder/embedder.h" #include "net/base/port_util.h" #include "ppapi/buildflags/buildflags.h" +#include "sandbox/policy/switches.h" #include "services/network/public/cpp/features.h" #include "services/network/public/cpp/network_switches.h" -#include "services/resource_coordinator/public/cpp/resource_coordinator_features.h" -#include "services/service_manager/sandbox/switches.h" +#include "services/network/public/mojom/network_context.mojom.h" +#include "services/service_manager/switches.h" +#include "services/tracing/public/cpp/trace_startup.h" #include "services/tracing/public/cpp/tracing_features.h" #include "third_party/blink/public/common/features.h" +#include "ui/base/ui_base_features.h" #include "ui/events/event_switches.h" #include "ui/native_theme/native_theme_features.h" #include "ui/gl/gl_switches.h" @@ -99,7 +112,7 @@ #include "base/mac/foundation_util.h" #endif -#ifndef QT_NO_ACCESSIBILITY +#if QT_CONFIG(accessibility) #include "accessibility_activation_observer.h" #endif #include "api/qwebengineurlscheme.h" @@ -118,7 +131,7 @@ #include <QGuiApplication> #include <QMutex> #include <QOffscreenSurface> -#ifndef QT_NO_OPENGL +#if QT_CONFIG(opengl) # include <QOpenGLContext> #endif #include <QQuickWindow> @@ -131,7 +144,7 @@ using namespace QtWebEngineCore; -#ifndef QT_NO_OPENGL +#if QT_CONFIG(opengl) QT_BEGIN_NAMESPACE Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context(); QT_END_NAMESPACE @@ -139,7 +152,7 @@ QT_END_NAMESPACE namespace { -#ifndef QT_NO_OPENGL +#if QT_CONFIG(opengl) bool usingANGLE() { #if defined(Q_OS_WIN) @@ -166,13 +179,13 @@ bool usingDefaultSGBackend() } if (device.isEmpty()) - device = QString::fromLocal8Bit(qgetenv("QT_QUICK_BACKEND")); + device = qEnvironmentVariable("QT_QUICK_BACKEND"); if (device.isEmpty()) - device = QString::fromLocal8Bit(qgetenv("QMLSCENE_DEVICE")); + device = qEnvironmentVariable("QMLSCENE_DEVICE"); return device.isEmpty(); } -#endif //QT_NO_OPENGL +#endif // QT_CONFIG(opengl) #if QT_CONFIG(webengine_pepper_plugins) void dummyGetPluginCallback(const std::vector<content::WebPluginInfo>&) { @@ -183,13 +196,25 @@ void dummyGetPluginCallback(const std::vector<content::WebPluginInfo>&) namespace QtWebEngineCore { +#if defined(Q_OS_WIN) +sandbox::SandboxInterfaceInfo *staticSandboxInterfaceInfo(sandbox::SandboxInterfaceInfo *info) +{ + static sandbox::SandboxInterfaceInfo *g_info = nullptr; + if (info) { + Q_ASSERT(g_info == nullptr); + g_info = info; + } + return g_info; +} +#endif + extern std::unique_ptr<base::MessagePump> messagePumpFactory(); bool usingSoftwareDynamicGL() { if (QCoreApplication::testAttribute(Qt::AA_UseSoftwareOpenGL)) return true; -#if defined(Q_OS_WIN) && !defined(QT_NO_OPENGL) +#if defined(Q_OS_WIN) && QT_CONFIG(opengl) HMODULE handle = static_cast<HMODULE>(QOpenGLContext::openGLModuleHandle()); wchar_t path[MAX_PATH]; DWORD size = GetModuleFileName(handle, path, MAX_PATH); @@ -200,9 +225,97 @@ bool usingSoftwareDynamicGL() #endif } +void setupProxyPac(base::CommandLine *commandLine){ + if (commandLine->HasSwitch(switches::kProxyPacUrl)) { + QUrl pac_url(toQt(commandLine->GetSwitchValueASCII(switches::kProxyPacUrl))); + if (pac_url.isValid() && (pac_url.isLocalFile() || + !pac_url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive))) { + QFile file; + if (pac_url.isLocalFile()) + file.setFileName(pac_url.toLocalFile()); + else + file.setFileName(pac_url.path().prepend(QChar(':'))); + if (file.exists() && file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QByteArray ba = file.readAll(); + commandLine->RemoveSwitch(switches::kProxyPacUrl); + commandLine->AppendSwitchASCII(switches::kProxyPacUrl, + ba.toBase64().prepend("data:application/x-javascript-config;base64,").toStdString()); + } + } + } +} + +static bool waitForViz = false; +static void completeVizCleanup() +{ + waitForViz = false; +} + +static void cleanupVizProcess() +{ + auto gpuChildThread = content::GpuChildThread::instance(); + if (!gpuChildThread) + return; + auto vizMain = gpuChildThread->viz_main(); + auto vizCompositorThreadRunner = vizMain->viz_compositor_thread_runner(); + if (!vizCompositorThreadRunner) + return; + waitForViz = true; + content::GetHostFrameSinkManager()->SetConnectionLostCallback(base::DoNothing()); + auto factory = static_cast<content::VizProcessTransportFactory*>(content::ImageTransportFactory::GetInstance()); + factory->PrepareForShutDown(); + vizCompositorThreadRunner->CleanupForShutdown(base::BindOnce(&completeVizCleanup)); +} + +static QStringList parseEnvCommandLine(const QString &cmdLine) +{ + QString arg; + QStringList arguments; + enum { Parse, Quoted, Unquoted } state = Parse; + for (const QChar c : cmdLine) { + switch (state) { + case Parse: + if (c == '"') { + state = Quoted; + } else if (c != ' ' ) { + arg += c; + state = Unquoted; + } + // skips spaces + break; + case Quoted: + if (c == '"') { + DCHECK(!arg.isEmpty()); + state = Unquoted; + } else { + // includes spaces + arg += c; + } + break; + case Unquoted: + if (c == '"') { + // skips quotes + state = Quoted; + } else if (c == ' ') { + arguments.append(arg); + arg.clear(); + state = Parse; + } else { + arg += c; + } + break; + } + } + // last arg + if (!arg.isEmpty()) { + arguments.append(arg); + } + return arguments; +} + scoped_refptr<QtWebEngineCore::WebEngineContext> WebEngineContext::m_handle; bool WebEngineContext::m_destroyed = false; - +bool WebEngineContext::m_closingDown = false; void WebEngineContext::destroyProfileAdapter() { if (content::RenderProcessHost::run_renderer_in_process()) { @@ -217,7 +330,7 @@ void WebEngineContext::addProfileAdapter(ProfileAdapter *profileAdapter) { Q_ASSERT(!m_profileAdapters.contains(profileAdapter)); const QString path = profileAdapter->dataPath(); - if (!path.isEmpty()) { + if (!profileAdapter->isOffTheRecord() && !profileAdapter->storageName().isEmpty()) { for (auto profileAdapter : m_profileAdapters) { if (profileAdapter->dataPath() == path) { // QTBUG-66068 @@ -241,21 +354,36 @@ void WebEngineContext::removeProfileAdapter(ProfileAdapter *profileAdapter) m_profileAdapters.removeAll(profileAdapter); } +void WebEngineContext::flushMessages() +{ + if (!m_destroyed) { + base::MessagePump::Delegate *delegate = static_cast< + base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl *>( + WebEngineContext::current()->m_runLoop->delegate_); + while (delegate->DoWork().is_immediate()) { } + } +} void WebEngineContext::destroy() { if (m_devtoolsServer) m_devtoolsServer->stop(); +#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) + if (m_webrtcLogUploader) + m_webrtcLogUploader->Shutdown(); +#endif + // Normally the GPU thread is shut down when the GpuProcessHost is destroyed // on IO thread (triggered by ~BrowserMainRunner). But by that time the UI // task runner is not working anymore so we need to do this earlier. + cleanupVizProcess(); + while (waitForViz) { + flushMessages(); + QThread::msleep(50); + } destroyGpuProcess(); - - base::MessagePump::Delegate *delegate = - static_cast<base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl *>( - m_runLoop->delegate_); // Flush the UI message loop before quitting. - while (delegate->DoWork()) { } + flushMessages(); #if QT_CONFIG(webengine_printing_and_pdf) // Kill print job manager early as it has a content::NotificationRegistrar @@ -277,14 +405,15 @@ void WebEngineContext::destroy() // Handle any events posted by browser-context shutdown. // This should deliver all nessesery calls of DeleteSoon from PostTask - while (delegate->DoWork()) { } + flushMessages(); - GLContextHelper::destroy(); m_devtoolsServer.reset(); m_runLoop->AfterRun(); // Destroy the main runner, this stops main message loop m_browserRunner.reset(); + // gpu thread is no longer around, so no more cotnext is used, remove the helper + GLContextHelper::destroy(); // These would normally be in the content-runner, but we allocated them separately: m_startupData.reset(); @@ -297,6 +426,10 @@ void WebEngineContext::destroy() // Drop the false reference. m_handle->Release(); + +#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) + m_webrtcLogUploader.reset(); +#endif } WebEngineContext::~WebEngineContext() @@ -351,6 +484,7 @@ void WebEngineContext::destroyContextPostRoutine() // Destroy WebEngineContext before its static pointer is zeroed and destructor called. // Before destroying MessageLoop via destroying BrowserMainRunner destructor // WebEngineContext's pointer is used. + m_closingDown = true; m_handle->destroy(); #if !defined(NDEBUG) if (!m_handle->HasOneRef()) @@ -381,23 +515,58 @@ const static char kChromiumFlagsEnv[] = "QTWEBENGINE_CHROMIUM_FLAGS"; const static char kDisableSandboxEnv[] = "QTWEBENGINE_DISABLE_SANDBOX"; const static char kDisableInProcGpuThread[] = "QTWEBENGINE_DISABLE_GPU_THREAD"; -static void appendToFeatureList(std::string &featureList, const char *feature) +// static +bool WebEngineContext::isGpuServiceOnUIThread() { - if (featureList.empty()) - featureList = feature; - else - featureList = featureList + "," + feature; + static bool threadedGpu = +#if QT_CONFIG(opengl) && !defined(Q_OS_MACOS) + QOpenGLContext::supportsThreadedOpenGL() && +#endif + !qEnvironmentVariableIsSet(kDisableInProcGpuThread); + return !threadedGpu; } -static void appendToFeatureSwitch(base::CommandLine *commandLine, const char *featureSwitch, std::string feature) +static void initializeFeatureList(base::CommandLine *commandLine, std::vector<std::string> enableFeatures, std::vector<std::string> disableFeatures) { - if (!commandLine->HasSwitch(featureSwitch)) { - commandLine->AppendSwitchASCII(featureSwitch, feature); - } else { - std::string featureList = commandLine->GetSwitchValueASCII(featureSwitch); - featureList = featureList + "," + feature; - commandLine->AppendSwitchASCII(featureSwitch, featureList); + std::string enableFeaturesString = base::JoinString(enableFeatures, ","); + if (commandLine->HasSwitch(switches::kEnableFeatures)) { + std::string commandLineEnableFeatures = commandLine->GetSwitchValueASCII(switches::kEnableFeatures); + + for (const std::string &enableFeature : base::SplitString(commandLineEnableFeatures, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) { + auto it = std::find(disableFeatures.begin(), disableFeatures.end(), enableFeature); + if (it == disableFeatures.end()) + continue; + + qWarning("An unsupported feature has been enabled from command line: %s\n" + "The feature is enabled but there is no guarantee that it will work or not break QtWebEngine.", enableFeature.c_str()); + + // If a feature is disabled and enabled at the same time, then it will be disabled. + // Remove feature from the disable list to make it possible to override from command line. + disableFeatures.erase(it); + } + + enableFeaturesString = enableFeaturesString + "," + commandLineEnableFeatures; + } + + std::string disableFeaturesString = base::JoinString(disableFeatures, ","); + if (commandLine->HasSwitch(switches::kDisableFeatures)) { + std::string commandLineDisableFeatures = commandLine->GetSwitchValueASCII(switches::kDisableFeatures); + + for (const std::string &disableFeature : base::SplitString(commandLineDisableFeatures, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) { + auto it = std::find(enableFeatures.begin(), enableFeatures.end(), disableFeature); + if (it == enableFeatures.end()) + continue; + + qWarning("An essential feature has been disabled from command line: %s\n" + "The feature is disabled but there is no guarantee that it will not break QtWebEngine.", disableFeature.c_str()); + } + + disableFeaturesString = disableFeaturesString + "," + commandLineDisableFeatures; } + + commandLine->AppendSwitchASCII(switches::kEnableFeatures, enableFeaturesString); + commandLine->AppendSwitchASCII(switches::kDisableFeatures, disableFeaturesString); + base::FeatureList::InitializeInstance(enableFeaturesString, disableFeaturesString); } WebEngineContext::WebEngineContext() @@ -411,7 +580,7 @@ WebEngineContext::WebEngineContext() #endif base::ThreadPoolInstance::Create("Browser"); - m_contentRunner.reset(content::ContentMainRunner::Create()); + m_contentRunner = content::ContentMainRunner::Create(); m_browserRunner = content::BrowserMainRunner::Create(); #ifdef Q_OS_LINUX @@ -450,38 +619,25 @@ WebEngineContext::WebEngineContext() #endif base::CommandLine* parsedCommandLine = commandLine(); - + setupProxyPac(parsedCommandLine); parsedCommandLine->AppendSwitchPath(switches::kBrowserSubprocessPath, WebEngineLibraryInfo::getPath(content::CHILD_PROCESS_EXE)); + parsedCommandLine->AppendSwitchASCII(service_manager::switches::kApplicationName, QCoreApplication::applicationName().toUtf8().toPercentEncoding().toStdString()); + // Enable sandboxing on OS X and Linux (Desktop / Embedded) by default. bool disable_sandbox = qEnvironmentVariableIsSet(kDisableSandboxEnv); if (!disable_sandbox) { -#if defined(Q_OS_WIN) - parsedCommandLine->AppendSwitch(service_manager::switches::kNoSandbox); -#elif defined(Q_OS_LINUX) - parsedCommandLine->AppendSwitch(service_manager::switches::kDisableSetuidSandbox); +#if defined(Q_OS_LINUX) + parsedCommandLine->AppendSwitch(sandbox::policy::switches::kDisableSetuidSandbox); #endif } else { - parsedCommandLine->AppendSwitch(service_manager::switches::kNoSandbox); + parsedCommandLine->AppendSwitch(sandbox::policy::switches::kNoSandbox); qInfo() << "Sandboxing disabled by user."; } parsedCommandLine->AppendSwitch(switches::kEnableThreadedCompositing); - // These are currently only default on OS X, and we don't support them: - parsedCommandLine->AppendSwitch(switches::kDisableZeroCopy); - parsedCommandLine->AppendSwitch(switches::kDisableGpuMemoryBufferCompositorResources); - - // Enabled on OS X and Linux but currently not working. It worked in 5.7 on OS X. - parsedCommandLine->AppendSwitch(switches::kDisableGpuMemoryBufferVideoFrames); - -#if defined(Q_OS_MACOS) - // Accelerated decoding currently does not work on macOS due to issues with OpenGL Rectangle - // texture support. See QTBUG-60002. - parsedCommandLine->AppendSwitch(switches::kDisableAcceleratedVideoDecode); - // Same problem with Pepper using OpenGL images. - parsedCommandLine->AppendSwitch(switches::kDisablePepper3DImageChromium); -#endif +#if QT_CONFIG(opengl) #if defined(Q_OS_WIN) // This switch is used in Chromium's gl_context_wgl.cc file to determine whether to create // an OpenGL Core Profile context. If the switch is not set, it would always try to create a @@ -504,79 +660,63 @@ WebEngineContext::WebEngineContext() if (isDesktopGLOrSoftware || isGLES2Context) parsedCommandLine->AppendSwitch(switches::kDisableES3GLContext); -#endif +#endif // defined(Q_OS_WIN) +#endif // QT_CONFIG(opengl) - bool threadedGpu = true; -#ifndef QT_NO_OPENGL - threadedGpu = QOpenGLContext::supportsThreadedOpenGL(); -#endif - threadedGpu = threadedGpu && !qEnvironmentVariableIsSet(kDisableInProcGpuThread); - - bool enableViz = ((threadedGpu && !parsedCommandLine->HasSwitch("disable-viz-display-compositor")) - || parsedCommandLine->HasSwitch("enable-viz-display-compositor")); - parsedCommandLine->RemoveSwitch("disable-viz-display-compositor"); - parsedCommandLine->RemoveSwitch("enable-viz-display-compositor"); + // Do not advertise a feature we have removed at compile time + parsedCommandLine->AppendSwitch(switches::kDisableSpeechAPI); - std::string disableFeatures; - std::string enableFeatures; + std::vector<std::string> disableFeatures; + std::vector<std::string> enableFeatures; // Needed to allow navigations within pages that were set using setHtml(). One example is // tst_QWebEnginePage::acceptNavigationRequest. // This is deprecated behavior, and will be removed in a future Chromium version, as per // upstream Chromium commit ba52f56207a4b9d70b34880fbff2352e71a06422. - appendToFeatureList(enableFeatures, features::kAllowContentInitiatedDataUrlNavigations.name); + enableFeatures.push_back(features::kAllowContentInitiatedDataUrlNavigations.name); - appendToFeatureList(enableFeatures, features::kTracingServiceInProcess.name); + enableFeatures.push_back(features::kNetworkServiceInProcess.name); + enableFeatures.push_back(features::kTracingServiceInProcess.name); // The video-capture service is not functioning at this moment (since 69) - appendToFeatureList(disableFeatures, features::kMojoVideoCapture.name); + disableFeatures.push_back(features::kMojoVideoCapture.name); + +#if defined(Q_OS_LINUX) + // broken and crashy (even upstream): + disableFeatures.push_back(features::kFontSrcLocalMatching.name); +#endif - // We do not yet fully support the network-service, but it has been enabled by default since 75. - bool enableNetworkService = parsedCommandLine->HasSwitch("enable-network-service"); - parsedCommandLine->RemoveSwitch("enable-network-service"); - if (!enableNetworkService) - appendToFeatureList(disableFeatures, network::features::kNetworkService.name); + // We don't support the skia renderer (enabled by default on Linux since 80) + disableFeatures.push_back(features::kUseSkiaRenderer.name); - // BlinkGenPropertyTrees is enabled by default in 75, but causes regressions. - appendToFeatureList(disableFeatures, blink::features::kBlinkGenPropertyTrees.name); + disableFeatures.push_back(network::features::kDnsOverHttpsUpgrade.name); -#if QT_CONFIG(webengine_printing_and_pdf) - appendToFeatureList(disableFeatures, printing::features::kUsePdfCompositorServiceForPrint.name); -#endif + // When enabled, event.movement is calculated in blink instead of in browser. + disableFeatures.push_back(features::kConsolidatedMovementXY.name); + + // Avoid crashing when websites tries using this feature (since 83) + disableFeatures.push_back(features::kInstalledApp.name); // Explicitly tell Chromium about default-on features we do not support - appendToFeatureList(disableFeatures, features::kBackgroundFetch.name); - appendToFeatureList(disableFeatures, features::kOriginTrials.name); - appendToFeatureList(disableFeatures, features::kSmsReceiver.name); - appendToFeatureList(disableFeatures, features::kWebAuth.name); - appendToFeatureList(disableFeatures, features::kWebAuthCable.name); - appendToFeatureList(disableFeatures, features::kWebPayments.name); - appendToFeatureList(disableFeatures, features::kWebUsb.name); + disableFeatures.push_back(features::kBackgroundFetch.name); + disableFeatures.push_back(features::kSmsReceiver.name); + disableFeatures.push_back(features::kWebPayments.name); + disableFeatures.push_back(features::kWebUsb.name); + disableFeatures.push_back(media::kPictureInPicture.name); if (useEmbeddedSwitches) { // embedded switches are based on the switches for Android, see content/browser/android/content_startup_flags.cc - appendToFeatureList(enableFeatures, features::kOverlayScrollbar.name); + enableFeatures.push_back(features::kOverlayScrollbar.name); parsedCommandLine->AppendSwitch(switches::kEnableViewport); parsedCommandLine->AppendSwitch(switches::kMainFrameResizesAreOrientationChanges); parsedCommandLine->AppendSwitch(cc::switches::kDisableCompositedAntialiasing); } - if (!enableViz) { - // Viz Display Compositor is enabled by default since 73. Doesn't work for us (also implies SurfaceSynchronization) - appendToFeatureList(disableFeatures, features::kVizDisplayCompositor.name); - // VideoSurfaceLayer is enabled by default since 75. We don't support it. - appendToFeatureList(disableFeatures, media::kUseSurfaceLayerForVideo.name); - } - - appendToFeatureSwitch(parsedCommandLine, switches::kDisableFeatures, disableFeatures); - appendToFeatureSwitch(parsedCommandLine, switches::kEnableFeatures, enableFeatures); - base::FeatureList::InitializeInstance( - parsedCommandLine->GetSwitchValueASCII(switches::kEnableFeatures), - parsedCommandLine->GetSwitchValueASCII(switches::kDisableFeatures)); + initializeFeatureList(parsedCommandLine, enableFeatures, disableFeatures); GLContextHelper::initialize(); const char *glType = 0; -#ifndef QT_NO_OPENGL +#if QT_CONFIG(opengl) const bool tryGL = (usingDefaultSGBackend() && !usingSoftwareDynamicGL() && QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) @@ -642,7 +782,7 @@ WebEngineContext::WebEngineContext() qWarning("WebEngineContext used before QtWebEngine::initialize() or OpenGL context creation failed."); } } -#endif +#endif // QT_CONFIG(opengl) if (glType) { parsedCommandLine->AppendSwitchASCII(switches::kUseGL, glType); @@ -655,15 +795,17 @@ WebEngineContext::WebEngineContext() parsedCommandLine->AppendSwitch(switches::kDisableGpu); } - registerMainThreadFactories(threadedGpu); - - SetContentClient(new ContentClientQt); + registerMainThreadFactories(); content::ContentMainParams contentMainParams(m_mainDelegate.get()); + contentMainParams.setup_signal_handlers = false; #if defined(OS_WIN) + contentMainParams.sandbox_info = staticSandboxInterfaceInfo(); sandbox::SandboxInterfaceInfo sandbox_info = {0}; - content::InitializeSandboxInfo(&sandbox_info); - contentMainParams.sandbox_info = &sandbox_info; + if (!contentMainParams.sandbox_info) { + content::InitializeSandboxInfo(&sandbox_info); + contentMainParams.sandbox_info = &sandbox_info; + } #endif m_contentRunner->Initialize(contentMainParams); @@ -678,13 +820,12 @@ WebEngineContext::WebEngineContext() m_mainDelegate->PostEarlyInitialization(false); content::StartBrowserThreadPool(); content::BrowserTaskExecutor::PostFeatureListSetup(); + tracing::InitTracingPostThreadPoolStartAndFeatureList(); m_discardableSharedMemoryManager = std::make_unique<discardable_memory::DiscardableSharedMemoryManager>(); + base::PowerMonitor::Initialize(std::make_unique<base::PowerMonitorDeviceSource>()); m_serviceManagerEnvironment = std::make_unique<content::ServiceManagerEnvironment>(content::BrowserTaskExecutor::CreateIOThread()); m_startupData = m_serviceManagerEnvironment->CreateBrowserStartupData(); - if (base::FeatureList::IsEnabled(network::features::kNetworkService)) - content::ForceInProcessNetworkService(true); - // Once the MessageLoop has been created, attach a top-level RunLoop. m_runLoop.reset(new base::RunLoop); m_runLoop->BeforeRun(); @@ -728,7 +869,7 @@ WebEngineContext::WebEngineContext() m_printJobManager.reset(new printing::PrintJobManager()); #endif -#ifndef QT_NO_ACCESSIBILITY +#if QT_CONFIG(accessibility) m_accessibilityActivationObserver.reset(new AccessibilityActivationObserver()); #endif @@ -742,6 +883,16 @@ printing::PrintJobManager* WebEngineContext::getPrintJobManager() } #endif +#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) +WebRtcLogUploader *WebEngineContext::webRtcLogUploader() +{ + if (!m_webrtcLogUploader) + m_webrtcLogUploader = std::make_unique<WebRtcLogUploader>(); + return m_webrtcLogUploader.get(); +} +#endif + + static QMutex s_spmMutex; QAtomicPointer<gpu::SyncPointManager> WebEngineContext::s_syncPointManager; @@ -761,7 +912,7 @@ base::CommandLine* WebEngineContext::commandLine() { QStringList appArgs = QCoreApplication::arguments(); if (qEnvironmentVariableIsSet(kChromiumFlagsEnv)) { appArgs = appArgs.mid(0, 1); // Take application name and drop the rest - appArgs.append(QString::fromLocal8Bit(qgetenv(kChromiumFlagsEnv)).split(' ')); + appArgs.append(parseEnvCommandLine(qEnvironmentVariable(kChromiumFlagsEnv))); } #ifdef Q_OS_WIN appArgs.removeAll(QStringLiteral("--enable-webgl-software-rendering")); @@ -785,4 +936,9 @@ base::CommandLine* WebEngineContext::commandLine() { } } +bool WebEngineContext::closingDown() +{ + return m_closingDown; +} + } // namespace diff --git a/src/core/web_engine_context.h b/src/core/web_engine_context.h index 5892017c5..2e74a766c 100644 --- a/src/core/web_engine_context.h +++ b/src/core/web_engine_context.h @@ -40,9 +40,13 @@ #ifndef WEB_ENGINE_CONTEXT_H #define WEB_ENGINE_CONTEXT_H +#include "qtwebenginecoreglobal_p.h" + #include "build_config_qt.h" #include "base/memory/ref_counted.h" #include "base/values.h" + +#include <QtGui/qtgui-config.h> #include <QVector> namespace base { @@ -75,7 +79,14 @@ class PrintJobManager; } #endif +#ifdef Q_OS_WIN +namespace sandbox { +struct SandboxInterfaceInfo; +} +#endif + QT_FORWARD_DECLARE_CLASS(QObject) +class WebRtcLogUploader; namespace QtWebEngineCore { @@ -86,6 +97,10 @@ class ProfileAdapter; bool usingSoftwareDynamicGL(); +#ifdef Q_OS_WIN +Q_WEBENGINECORE_PRIVATE_EXPORT sandbox::SandboxInterfaceInfo *staticSandboxInterfaceInfo(sandbox::SandboxInterfaceInfo *info = nullptr); +#endif + typedef std::tuple<bool, QString, QString> ProxyAuthentication; class WebEngineContext : public base::RefCounted<WebEngineContext> { @@ -93,7 +108,8 @@ public: static WebEngineContext *current(); static void destroyContextPostRoutine(); static ProxyAuthentication qProxyNetworkAuthentication(QString host, int port); - + static void flushMessages(); + static bool closingDown(); ProfileAdapter *createDefaultProfileAdapter(); ProfileAdapter *defaultProfileAdapter(); @@ -101,6 +117,9 @@ public: #if QT_CONFIG(webengine_printing_and_pdf) printing::PrintJobManager* getPrintJobManager(); #endif +#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) + WebRtcLogUploader *webRtcLogUploader(); +#endif void destroyProfileAdapter(); void addProfileAdapter(ProfileAdapter *profileAdapter); void removeProfileAdapter(ProfileAdapter *profileAdapter); @@ -109,13 +128,15 @@ public: static gpu::SyncPointManager *syncPointManager(); + static bool isGpuServiceOnUIThread(); + private: friend class base::RefCounted<WebEngineContext>; friend class ProfileAdapter; WebEngineContext(); ~WebEngineContext(); - static void registerMainThreadFactories(bool threaded); + static void registerMainThreadFactories(); static void destroyGpuProcess(); std::unique_ptr<base::RunLoop> m_runLoop; @@ -129,15 +150,19 @@ private: std::unique_ptr<ProfileAdapter> m_defaultProfileAdapter; std::unique_ptr<DevToolsServerQt> m_devtoolsServer; QVector<ProfileAdapter*> m_profileAdapters; -#ifndef QT_NO_ACCESSIBILITY +#if QT_CONFIG(accessibility) std::unique_ptr<AccessibilityActivationObserver> m_accessibilityActivationObserver; #endif #if QT_CONFIG(webengine_printing_and_pdf) std::unique_ptr<printing::PrintJobManager> m_printJobManager; #endif +#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) + std::unique_ptr<WebRtcLogUploader> m_webrtcLogUploader; +#endif static scoped_refptr<QtWebEngineCore::WebEngineContext> m_handle; static bool m_destroyed; + static bool m_closingDown; static QAtomicPointer<gpu::SyncPointManager> s_syncPointManager; }; diff --git a/src/core/web_engine_context_threads.cpp b/src/core/web_engine_context_threads.cpp index e92cf3e9b..5aa4c3e1e 100644 --- a/src/core/web_engine_context_threads.cpp +++ b/src/core/web_engine_context_threads.cpp @@ -57,19 +57,21 @@ #include <memory> +#include <QEventLoop> + namespace QtWebEngineCore { struct GpuThreadControllerQt : content::GpuThreadController { GpuThreadControllerQt(const content::InProcessChildThreadParams ¶ms, const gpu::GpuPreferences &gpuPreferences) { - base::PostTaskWithTraits( + base::PostTask( FROM_HERE, { content::BrowserThread::UI }, base::BindOnce(&GpuThreadControllerQt::createGpuProcess, params, gpuPreferences)); } ~GpuThreadControllerQt() override { - base::PostTaskWithTraits( + base::PostTask( FROM_HERE, { content::BrowserThread::UI }, base::BindOnce(&GpuThreadControllerQt::destroyGpuProcess)); } @@ -82,7 +84,7 @@ struct GpuThreadControllerQt : content::GpuThreadController if (s_gpuProcessDestroyed) return; - s_gpuProcess = std::make_unique<content::GpuProcess>(base::ThreadPriority::DISPLAY); + s_gpuProcess = std::make_unique<content::GpuProcess>(base::ThreadPriority::NORMAL); auto gpuInit = std::make_unique<gpu::GpuInit>(); gpuInit->InitializeInProcess(base::CommandLine::ForCurrentProcess(), gpuPreferences); auto childThread = new content::GpuChildThread(params, std::move(gpuInit)); @@ -123,11 +125,11 @@ void WebEngineContext::destroyGpuProcess() } // static -void WebEngineContext::registerMainThreadFactories(bool threaded) +void WebEngineContext::registerMainThreadFactories() { content::UtilityProcessHost::RegisterUtilityMainThreadFactory(content::CreateInProcessUtilityThread); content::RenderProcessHostImpl::RegisterRendererMainThreadFactory(content::CreateInProcessRendererThread); - if (threaded) + if (!isGpuServiceOnUIThread()) content::RegisterGpuMainThreadFactory(content::CreateInProcessGpuThread); else content::RegisterGpuMainThreadFactory(createGpuThreadController); diff --git a/src/core/web_engine_library_info.cpp b/src/core/web_engine_library_info.cpp index 1c8316430..3a6492273 100644 --- a/src/core/web_engine_library_info.cpp +++ b/src/core/web_engine_library_info.cpp @@ -45,8 +45,11 @@ #include "base/files/file_util.h" #include "components/spellcheck/spellcheck_buildflags.h" #include "content/public/common/content_paths.h" +#include "sandbox/policy/switches.h" +#include "ui/base/l10n/l10n_util.h" #include "ui/base/ui_base_paths.h" #include "ui/base/ui_base_switches.h" + #include "type_conversion.h" #include <QByteArray> @@ -56,7 +59,10 @@ #include <QLibraryInfo> #include <QLocale> #include <QStandardPaths> -#include <QString> + +#if defined(OS_WIN) +#include <windows.h> +#endif // OS_WIN #ifndef QTWEBENGINEPROCESS_NAME #error "No name defined for QtWebEngine's process" @@ -71,7 +77,7 @@ QString fallbackDir() { return directory; } -#if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD) +#if defined(OS_MAC) && defined(QT_MAC_FRAMEWORK_BUILD) static inline CFBundleRef frameworkBundle() { return CFBundleGetBundleWithIdentifier(CFSTR("org.qt-project.Qt.QtWebEngineCore")); @@ -114,7 +120,7 @@ static QString getResourcesPath(CFBundleRef frameworkBundle) } #endif -#if defined(OS_MACOSX) +#if defined(OS_MAC) static QString getMainApplicationResourcesPath() { QString resourcesPath; @@ -153,12 +159,12 @@ QString subProcessPath() #endif QStringList candidatePaths; - const QByteArray fromEnv = qgetenv("QTWEBENGINEPROCESS_PATH"); + const QString fromEnv = qEnvironmentVariable("QTWEBENGINEPROCESS_PATH"); if (!fromEnv.isEmpty()) { // Only search in QTWEBENGINEPROCESS_PATH if set - candidatePaths << QString::fromLocal8Bit(fromEnv); + candidatePaths << fromEnv; } else { -#if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD) +#if defined(OS_MAC) && defined(QT_MAC_FRAMEWORK_BUILD) candidatePaths << getPath(frameworkBundle()) % QStringLiteral("/Helpers/" QTWEBENGINEPROCESS_NAME ".app/Contents/MacOS/" QTWEBENGINEPROCESS_NAME); #else @@ -178,6 +184,14 @@ QString subProcessPath() if (processPath.isEmpty()) qFatal("Could not find %s", processBinary.toUtf8().constData()); +#if defined(OS_WIN) + base::CommandLine *parsedCommandLine = base::CommandLine::ForCurrentProcess(); + if (!parsedCommandLine->HasSwitch(sandbox::policy::switches::kNoSandbox)) { + if (WebEngineLibraryInfo::isUNCPath(processPath) || WebEngineLibraryInfo::isRemoteDrivePath(processPath)) + qCritical("Can not launch QtWebEngineProcess from network path if sandbox is enabled: %s.", processPath.toUtf8().constData()); + } +#endif + } @@ -188,7 +202,7 @@ QString localesPath() { static bool initialized = false; static QString potentialLocalesPath = -#if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD) +#if defined(OS_MAC) && defined(QT_MAC_FRAMEWORK_BUILD) getResourcesPath(frameworkBundle()) % QLatin1String("/qtwebengine_locales"); #else QLibraryInfo::location(QLibraryInfo::TranslationsPath) % QDir::separator() % QLatin1String("qtwebengine_locales"); @@ -218,13 +232,13 @@ QString dictionariesPath() if (!initialized) { initialized = true; - const QByteArray fromEnv = qgetenv("QTWEBENGINE_DICTIONARIES_PATH"); + const QString fromEnv = qEnvironmentVariable("QTWEBENGINE_DICTIONARIES_PATH"); if (!fromEnv.isEmpty()) { // Only search in QTWEBENGINE_DICTIONARIES_PATH if set - candidatePaths << QString::fromLocal8Bit(fromEnv); + candidatePaths << fromEnv; } else { // First try to find dictionaries near the application. -#ifdef OS_MACOSX +#ifdef OS_MAC QString resourcesDictionariesPath = getMainApplicationResourcesPath() % QDir::separator() % QLatin1String("qtwebengine_dictionaries"); candidatePaths << resourcesDictionariesPath; @@ -234,7 +248,7 @@ QString dictionariesPath() candidatePaths << applicationDictionariesPath; // Then try to find dictionaries near the installed library. -#if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD) +#if defined(OS_MAC) && defined(QT_MAC_FRAMEWORK_BUILD) QString frameworkDictionariesPath = getResourcesPath(frameworkBundle()) % QLatin1String("/qtwebengine_dictionaries"); candidatePaths << frameworkDictionariesPath; @@ -261,8 +275,10 @@ QString resourcesDataPath() { static bool initialized = false; static QString potentialResourcesPath = -#if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD) +#if defined(OS_MAC) && defined(QT_MAC_FRAMEWORK_BUILD) getResourcesPath(frameworkBundle()); +#elif defined(OS_MAC) + QLibraryInfo::location(QLibraryInfo::DataPath) % QLatin1String("/Resources"); #else QLibraryInfo::location(QLibraryInfo::DataPath) % QLatin1String("/resources"); #endif @@ -335,19 +351,42 @@ base::string16 WebEngineLibraryInfo::getApplicationName() return toString16(qApp->applicationName()); } -std::string WebEngineLibraryInfo::getApplicationLocale() +std::string WebEngineLibraryInfo::getResolvedLocale() { base::CommandLine *parsedCommandLine = base::CommandLine::ForCurrentProcess(); - if (!parsedCommandLine->HasSwitch(switches::kLang)) { + if (parsedCommandLine->HasSwitch(switches::kLang)) { + return parsedCommandLine->GetSwitchValueASCII(switches::kLang); + } else { const QString &locale = QLocale().bcp47Name(); + std::string resolvedLocale; + if (l10n_util::CheckAndResolveLocale(locale.toStdString(), &resolvedLocale)) + return resolvedLocale; + } + return "en-US"; +} - // QLocale::bcp47Name returns "en" for American English locale. Chromium requires the "US" suffix - // to clarify the dialect and ignores the shorter version. - if (locale == "en") - return "en-US"; +std::string WebEngineLibraryInfo::getApplicationLocale() +{ + base::CommandLine *parsedCommandLine = base::CommandLine::ForCurrentProcess(); + return parsedCommandLine->HasSwitch(switches::kLang) + ? parsedCommandLine->GetSwitchValueASCII(switches::kLang) + : QLocale().bcp47Name().toStdString(); +} - return locale.toStdString(); - } +#if defined(OS_WIN) +bool WebEngineLibraryInfo::isRemoteDrivePath(const QString &path) +{ + WCHAR wDriveLetter[4] = { 0 }; + swprintf(wDriveLetter, L"%S", path.mid(0, 3).toStdString().c_str()); + return GetDriveType(wDriveLetter) == DRIVE_REMOTE; +} - return parsedCommandLine->GetSwitchValueASCII(switches::kLang); +bool WebEngineLibraryInfo::isUNCPath(const QString &path) +{ + return (base::FilePath::IsSeparator(path.at(0).toLatin1()) + && base::FilePath::IsSeparator(path.at(1).toLatin1()) + && path.at(2) != "." && path.at(2) != "?" + && path.at(2).isLetter() && path.at(3) != ":"); } + +#endif diff --git a/src/core/web_engine_library_info.h b/src/core/web_engine_library_info.h index a5cd914d3..e7dc195f6 100644 --- a/src/core/web_engine_library_info.h +++ b/src/core/web_engine_library_info.h @@ -43,6 +43,8 @@ #include "base/files/file_path.h" #include "base/strings/string16.h" +#include <QString> + enum { QT_RESOURCES_PAK = 5000, QT_RESOURCES_100P_PAK = 5001, @@ -55,7 +57,12 @@ public: static base::FilePath getPath(int key); // Called by localized_error in our custom chrome layer static base::string16 getApplicationName(); + static std::string getResolvedLocale(); static std::string getApplicationLocale(); +#if defined(OS_WIN) + static bool isRemoteDrivePath(const QString &path); + static bool isUNCPath(const QString &path); +#endif }; diff --git a/src/core/web_engine_settings.cpp b/src/core/web_engine_settings.cpp index 49006ec20..4115d10d7 100644 --- a/src/core/web_engine_settings.cpp +++ b/src/core/web_engine_settings.cpp @@ -49,9 +49,9 @@ #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_switches.h" -#include "content/public/common/web_preferences.h" -#include "content/public/common/webrtc_ip_handling_policy.h" #include "media/base/media_switches.h" +#include "third_party/blink/public/common/peerconnection/webrtc_ip_handling_policy.h" +#include "third_party/blink/public/common/web_preferences/web_preferences.h" #include "third_party/blink/public/mojom/renderer_preferences.mojom.h" #include "ui/base/ui_base_switches.h" #include "ui/events/event_switches.h" @@ -112,12 +112,11 @@ WebEngineSettings::~WebEngineSettings() if (parentSettings) parentSettings->childSettings.remove(this); // In QML the profile and its settings may be garbage collected before the page and its settings. - for (WebEngineSettings *settings : qAsConst(childSettings)) { - settings->parentSettings = 0; - } + for (WebEngineSettings *settings : qAsConst(childSettings)) + settings->parentSettings = nullptr; } -void WebEngineSettings::overrideWebPreferences(content::WebContents *webContents, content::WebPreferences *prefs) +void WebEngineSettings::overrideWebPreferences(content::WebContents *webContents, blink::web_pref::WebPreferences *prefs) { // Apply our settings on top of those. applySettingsToWebPreferences(prefs); @@ -125,12 +124,11 @@ void WebEngineSettings::overrideWebPreferences(content::WebContents *webContents // as the host process already overides some of the default WebPreferences values // before we get here (e.g. number_of_cpu_cores). if (webPreferences.isNull()) - webPreferences.reset(new content::WebPreferences(*prefs)); + webPreferences.reset(new blink::web_pref::WebPreferences(*prefs)); if (webContents - && webContents->GetRenderViewHost() && applySettingsToRendererPreferences(webContents->GetMutableRendererPrefs())) { - webContents->GetRenderViewHost()->SyncRendererPrefs(); + webContents->SyncRendererPrefs(); } } @@ -142,11 +140,15 @@ void WebEngineSettings::setAttribute(WebEngineSettings::Attribute attr, bool on) bool WebEngineSettings::testAttribute(WebEngineSettings::Attribute attr) const { - if (!parentSettings) { - Q_ASSERT(s_defaultAttributes.contains(attr)); - return m_attributes.value(attr, s_defaultAttributes.value(attr)); - } - return m_attributes.value(attr, parentSettings->testAttribute(attr)); + auto it = m_attributes.constFind(attr); + if (it != m_attributes.constEnd()) + return *it; + + if (parentSettings) + return parentSettings->testAttribute(attr); + + Q_ASSERT(s_defaultAttributes.contains(attr)); + return s_defaultAttributes.value(attr); } bool WebEngineSettings::isAttributeExplicitlySet(Attribute attr) const @@ -248,7 +250,7 @@ void WebEngineSettings::initDefaults() s_defaultAttributes.insert(LinksIncludedInFocusChain, true); s_defaultAttributes.insert(LocalStorageEnabled, true); s_defaultAttributes.insert(LocalContentCanAccessRemoteUrls, false); - s_defaultAttributes.insert(XSSAuditingEnabled, true); + s_defaultAttributes.insert(XSSAuditingEnabled, false); s_defaultAttributes.insert(SpatialNavigationEnabled, false); s_defaultAttributes.insert(LocalContentCanAccessFileUrls, true); s_defaultAttributes.insert(HyperlinkAuditingEnabled, false); @@ -334,16 +336,18 @@ void WebEngineSettings::doApply() { if (webPreferences.isNull()) return; + + m_batchTimer.stop(); // Override with our settings when applicable applySettingsToWebPreferences(webPreferences.data()); Q_ASSERT(m_adapter); m_adapter->updateWebPreferences(*webPreferences.data()); if (applySettingsToRendererPreferences(m_adapter->webContents()->GetMutableRendererPrefs())) - m_adapter->webContents()->GetRenderViewHost()->SyncRendererPrefs(); + m_adapter->webContents()->SyncRendererPrefs(); } -void WebEngineSettings::applySettingsToWebPreferences(content::WebPreferences *prefs) +void WebEngineSettings::applySettingsToWebPreferences(blink::web_pref::WebPreferences *prefs) { // Override for now prefs->touch_event_feature_detection_enabled = isTouchEventsAPIEnabled(); @@ -366,7 +370,6 @@ void WebEngineSettings::applySettingsToWebPreferences(content::WebPreferences *p prefs->local_storage_enabled = testAttribute(LocalStorageEnabled); prefs->databases_enabled = testAttribute(LocalStorageEnabled); prefs->allow_universal_access_from_file_urls = testAttribute(LocalContentCanAccessRemoteUrls); - prefs->xss_auditor_enabled = testAttribute(XSSAuditingEnabled); prefs->spatial_navigation_enabled = testAttribute(SpatialNavigationEnabled); prefs->allow_file_access_from_file_urls = testAttribute(LocalContentCanAccessFileUrls); prefs->hyperlink_auditing_enabled = testAttribute(HyperlinkAuditingEnabled); @@ -382,20 +385,20 @@ void WebEngineSettings::applySettingsToWebPreferences(content::WebPreferences *p prefs->hide_scrollbars = !testAttribute(ShowScrollBars); if (isAttributeExplicitlySet(PlaybackRequiresUserGesture)) { prefs->autoplay_policy = testAttribute(PlaybackRequiresUserGesture) - ? content::AutoplayPolicy::kUserGestureRequired - : content::AutoplayPolicy::kNoUserGestureRequired; + ? blink::web_pref::AutoplayPolicy::kUserGestureRequired + : blink::web_pref::AutoplayPolicy::kNoUserGestureRequired; } prefs->dom_paste_enabled = testAttribute(JavascriptCanPaste); prefs->dns_prefetching_enabled = testAttribute(DnsPrefetchEnabled); // Fonts settings. - prefs->standard_font_family_map[content::kCommonScript] = toString16(fontFamily(StandardFont)); - prefs->fixed_font_family_map[content::kCommonScript] = toString16(fontFamily(FixedFont)); - prefs->serif_font_family_map[content::kCommonScript] = toString16(fontFamily(SerifFont)); - prefs->sans_serif_font_family_map[content::kCommonScript] = toString16(fontFamily(SansSerifFont)); - prefs->cursive_font_family_map[content::kCommonScript] = toString16(fontFamily(CursiveFont)); - prefs->fantasy_font_family_map[content::kCommonScript] = toString16(fontFamily(FantasyFont)); - prefs->pictograph_font_family_map[content::kCommonScript] = toString16(fontFamily(PictographFont)); + prefs->standard_font_family_map[blink::web_pref::kCommonScript] = toString16(fontFamily(StandardFont)); + prefs->fixed_font_family_map[blink::web_pref::kCommonScript] = toString16(fontFamily(FixedFont)); + prefs->serif_font_family_map[blink::web_pref::kCommonScript] = toString16(fontFamily(SerifFont)); + prefs->sans_serif_font_family_map[blink::web_pref::kCommonScript] = toString16(fontFamily(SansSerifFont)); + prefs->cursive_font_family_map[blink::web_pref::kCommonScript] = toString16(fontFamily(CursiveFont)); + prefs->fantasy_font_family_map[blink::web_pref::kCommonScript] = toString16(fontFamily(FantasyFont)); + prefs->pictograph_font_family_map[blink::web_pref::kCommonScript] = toString16(fontFamily(PictographFont)); prefs->default_font_size = fontSize(DefaultFontSize); prefs->default_fixed_font_size = fontSize(DefaultFixedFontSize); prefs->minimum_font_size = fontSize(MinimumFontSize); @@ -405,12 +408,6 @@ void WebEngineSettings::applySettingsToWebPreferences(content::WebPreferences *p // Set the theme colors. Based on chrome_content_browser_client.cc: const ui::NativeTheme *webTheme = ui::NativeTheme::GetInstanceForWeb(); if (webTheme) { -#if !defined(OS_MACOSX) - // Mac has a concept of high contrast that does not relate to forced colors. - prefs->forced_colors = webTheme->UsesHighContrastColors() - ? blink::ForcedColors::kActive - : blink::ForcedColors::kNone; -#endif // !defined(OS_MACOSX) switch (webTheme->GetPreferredColorScheme()) { case ui::NativeTheme::PreferredColorScheme::kDark: prefs->preferred_color_scheme = blink::PreferredColorScheme::kDark; @@ -418,8 +415,6 @@ void WebEngineSettings::applySettingsToWebPreferences(content::WebPreferences *p case ui::NativeTheme::PreferredColorScheme::kLight: prefs->preferred_color_scheme = blink::PreferredColorScheme::kLight; break; - case ui::NativeTheme::PreferredColorScheme::kNoPreference: - prefs->preferred_color_scheme = blink::PreferredColorScheme::kNoPreference; } } @@ -453,8 +448,8 @@ bool WebEngineSettings::applySettingsToRendererPreferences(blink::mojom::Rendere #if QT_CONFIG(webengine_webrtc) if (!base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kForceWebRtcIPHandlingPolicy)) { std::string webrtc_ip_handling_policy = testAttribute(WebEngineSettings::WebRTCPublicInterfacesOnly) - ? content::kWebRTCIPHandlingDefaultPublicInterfaceOnly - : content::kWebRTCIPHandlingDefault; + ? blink::kWebRTCIPHandlingDefaultPublicInterfaceOnly + : blink::kWebRTCIPHandlingDefault; if (prefs->webrtc_ip_handling_policy != webrtc_ip_handling_policy) { prefs->webrtc_ip_handling_policy = webrtc_ip_handling_policy; changed = true; diff --git a/src/core/web_engine_settings.h b/src/core/web_engine_settings.h index 95eea669f..d97ff5767 100644 --- a/src/core/web_engine_settings.h +++ b/src/core/web_engine_settings.h @@ -61,12 +61,15 @@ namespace content { class WebContents; -struct WebPreferences; } + namespace blink { namespace mojom { class RendererPreferences; } +namespace web_pref { +struct WebPreferences; +} } namespace QtWebEngineCore { @@ -142,7 +145,7 @@ public: void setParentSettings(WebEngineSettings *parentSettings); - void overrideWebPreferences(content::WebContents *webContents, content::WebPreferences *prefs); + void overrideWebPreferences(content::WebContents *webContents, blink::web_pref::WebPreferences *prefs); void setAttribute(Attribute, bool on); bool testAttribute(Attribute) const; @@ -172,7 +175,7 @@ public: private: void doApply(); - void applySettingsToWebPreferences(content::WebPreferences *); + void applySettingsToWebPreferences(blink::web_pref::WebPreferences *); bool applySettingsToRendererPreferences(blink::mojom::RendererPreferences *); void setWebContentsAdapter(WebContentsAdapter *adapter) { m_adapter = adapter; } @@ -181,7 +184,7 @@ private: QHash<FontFamily, QString> m_fontFamilies; QHash<FontSize, int> m_fontSizes; QString m_defaultEncoding; - QScopedPointer<content::WebPreferences> webPreferences; + QScopedPointer<blink::web_pref::WebPreferences> webPreferences; QTimer m_batchTimer; WebEngineSettings *parentSettings; diff --git a/src/core/web_event_factory.cpp b/src/core/web_event_factory.cpp index ba04806d5..b6ca70294 100644 --- a/src/core/web_event_factory.cpp +++ b/src/core/web_event_factory.cpp @@ -71,6 +71,8 @@ #include "ui/events/keycodes/dom/keycode_converter.h" #include "ui/events/keycodes/keyboard_code_conversion.h" +#include "render_widget_host_view_qt_delegate.h" + #include <QtGui/private/qtgui-config_p.h> #include <QCoreApplication> @@ -84,6 +86,8 @@ #endif #include <QWheelEvent> +namespace QtWebEngineCore { + using namespace blink; enum class KeyboardDriver { Unknown, Windows, Cocoa, Xkb, Evdev }; @@ -157,8 +161,11 @@ static Qt::KeyboardModifiers qtModifiersForEvent(const QInputEvent *ev) // // On Linux, the Control modifier transformation is applied [1]. For example, // pressing Ctrl+@ generates the text "\u0000". We would like "@" instead. +// Windows also translates some control key combinations into ASCII control +// characters [2]. // // [1]: https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Control_Modifier +// [2]: https://docs.microsoft.com/en-us/windows/win32/learnwin32/keyboard-input#character-messages // // On macOS, if the Control modifier is used, then no text is generated at all. // We need some text. @@ -171,8 +178,15 @@ static QString qtTextForKeyEvent(const QKeyEvent *ev, int qtKey, Qt::KeyboardMod { QString text = ev->text(); - if ((qtModifiers & Qt::ControlModifier) && keyboardDriver() == KeyboardDriver::Xkb) + if (keyboardDriver() == KeyboardDriver::Xkb && (qtModifiers & Qt::ControlModifier)) { + text.clear(); + } + + // Keep text for Ctrl+Alt key combinations on Windows. It is an alternative for AltGr. + if (keyboardDriver() == KeyboardDriver::Windows + && (qtModifiers & Qt::ControlModifier) && !(qtModifiers & Qt::AltModifier)) { text.clear(); + } return text; } @@ -191,10 +205,20 @@ static quint32 nativeKeyCodeForKeyEvent(const QKeyEvent *ev) // Cygwin/X, etc). Also evdev key codes are *not* supported for the same // reason. #if defined(Q_OS_WINDOWS) - return keyboardDriver() == KeyboardDriver::Windows ? ev->nativeScanCode() : 0; + if (keyboardDriver() == KeyboardDriver::Windows) { + // see GetScanCodeFromLParam in events_win_utils.cc: + quint32 scancode = ev->nativeScanCode() & 0xff; + if (ev->nativeScanCode() & 0x100) + scancode |= 0xe000; + return scancode; + } + return 0; #elif defined(Q_OS_MACOS) return keyboardDriver() == KeyboardDriver::Cocoa ? ev->nativeVirtualKey() : 0; #elif defined(Q_OS_LINUX) + // Do not set native code to menu key if it was mapped to something else. + if (ev->nativeScanCode() == 135 && ev->key() != Qt::Key_Menu) + return 0; return keyboardDriver() == KeyboardDriver::Xkb ? ev->nativeScanCode() : 0; #else return 0; // 0 means unknown, KeyboardEvent.code will be empty string. @@ -1213,8 +1237,12 @@ static WebMouseEvent::Button mouseButtonForEvent(T *event) return WebMouseEvent::Button::kLeft; else if (event->button() == Qt::RightButton) return WebMouseEvent::Button::kRight; - else if (event->button() == Qt::MidButton) + else if (event->button() == Qt::MiddleButton) return WebMouseEvent::Button::kMiddle; + else if (event->button() == Qt::BackButton) + return WebMouseEvent::Button::kBack; + else if (event->button() == Qt::ForwardButton) + return WebMouseEvent::Button::kForward; if (event->type() != QEvent::MouseMove && event->type() != QEvent::TabletMove) return WebMouseEvent::Button::kNoButton; @@ -1225,8 +1253,12 @@ static WebMouseEvent::Button mouseButtonForEvent(T *event) return WebMouseEvent::Button::kLeft; else if (event->buttons() & Qt::RightButton) return WebMouseEvent::Button::kRight; - else if (event->buttons() & Qt::MidButton) + else if (event->buttons() & Qt::MiddleButton) return WebMouseEvent::Button::kMiddle; + else if (event->buttons() & Qt::BackButton) + return WebMouseEvent::Button::kBack; + else if (event->buttons() & Qt::ForwardButton) + return WebMouseEvent::Button::kForward; return WebMouseEvent::Button::kNoButton; } @@ -1239,11 +1271,38 @@ static unsigned mouseButtonsModifiersForEvent(const T* event) ret |= WebInputEvent::kLeftButtonDown; if (event->buttons() & Qt::RightButton) ret |= WebInputEvent::kRightButtonDown; - if (event->buttons() & Qt::MidButton) + if (event->buttons() & Qt::MiddleButton) ret |= WebInputEvent::kMiddleButtonDown; + if (event->buttons() & Qt::BackButton) + ret |= WebInputEvent::kBackButtonDown; + if (event->buttons() & Qt::ForwardButton) + ret |= WebInputEvent::kForwardButtonDown; return ret; } +static WebInputEvent::Modifiers lockKeyModifiers(const quint32 nativeModifiers) +{ + unsigned result = 0; + if (keyboardDriver() == KeyboardDriver::Xkb) { + if (nativeModifiers & 0x42) /* Caps_Lock */ + result |= WebInputEvent::kCapsLockOn; + if (nativeModifiers & 0x4d) /* Num_Lock */ + result |= WebInputEvent::kNumLockOn; + } else if (keyboardDriver() == KeyboardDriver::Windows) { + if (nativeModifiers & 0x100) /* CapsLock */ + result |= WebInputEvent::kCapsLockOn; + if (nativeModifiers & 0x200) /* NumLock */ + result |= WebInputEvent::kNumLockOn; + if (nativeModifiers & 0x400) /* ScrollLock */ + result |= WebInputEvent::kScrollLockOn; + } else if (keyboardDriver() == KeyboardDriver::Cocoa) { + if (nativeModifiers & 0x10000) /* NSEventModifierFlagCapsLock */ + result |= WebInputEvent::kCapsLockOn; + } + + return static_cast<WebInputEvent::Modifiers>(result); +} + // If only a modifier key is pressed, Qt only reports the key code. // But Chromium also expects the modifier being set. static inline WebInputEvent::Modifiers modifierForKeyCode(int key) @@ -1292,13 +1351,54 @@ static inline WebInputEvent::Modifiers modifiersForEvent(const QInputEvent* even if (keyEvent->isAutoRepeat()) result |= WebInputEvent::kIsAutoRepeat; result |= modifierForKeyCode(qtKeyForKeyEvent(keyEvent)); + result |= lockKeyModifiers(keyEvent->nativeModifiers()); break; } default: break; } - return (WebInputEvent::Modifiers)result; + return static_cast<WebInputEvent::Modifiers>(result); +} + +static inline Qt::KeyboardModifiers keyboardModifiersForModifier(unsigned int modifier) +{ + Qt::KeyboardModifiers modifiers = {}; + if (modifier & WebInputEvent::kControlKey) + modifiers |= Qt::ControlModifier; + if (modifier & WebInputEvent::kMetaKey) + modifiers |= Qt::MetaModifier; + if (modifier & WebInputEvent::kShiftKey) + modifiers |= Qt::ShiftModifier; + if (modifier & WebInputEvent::kAltKey) + modifiers |= Qt::AltModifier; + if (modifier & WebInputEvent::kIsKeyPad) + modifiers |= Qt::KeypadModifier; + + if (keyboardDriver() == KeyboardDriver::Cocoa && !qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { + bool controlModifier = modifiers.testFlag(Qt::ControlModifier); + bool metaModifier = modifiers.testFlag(Qt::MetaModifier); + modifiers.setFlag(Qt::ControlModifier, metaModifier); + modifiers.setFlag(Qt::MetaModifier, controlModifier); + } + + return modifiers; +} + +static inline Qt::MouseButtons mouseButtonsForModifier(unsigned int modifier) +{ + Qt::MouseButtons buttons = {}; + if (modifier & WebInputEvent::kLeftButtonDown) + buttons |= Qt::LeftButton; + if (modifier & WebInputEvent::kRightButtonDown) + buttons |= Qt::RightButton; + if (modifier & WebInputEvent::kMiddleButtonDown) + buttons |= Qt::MiddleButton; + if (modifier & WebInputEvent::kBackButtonDown) + buttons |= Qt::BackButton; + if (modifier & WebInputEvent::kForwardButtonDown) + buttons |= Qt::ForwardButton; + return buttons; } static WebInputEvent::Type webEventTypeForEvent(const QEvent* event) @@ -1306,36 +1406,36 @@ static WebInputEvent::Type webEventTypeForEvent(const QEvent* event) switch (event->type()) { case QEvent::MouseButtonPress: case QEvent::TabletPress: - return WebInputEvent::kMouseDown; + return WebInputEvent::Type::kMouseDown; case QEvent::MouseButtonRelease: case QEvent::TabletRelease: - return WebInputEvent::kMouseUp; + return WebInputEvent::Type::kMouseUp; case QEvent::Enter: - return WebInputEvent::kMouseEnter; + return WebInputEvent::Type::kMouseEnter; case QEvent::Leave: - return WebInputEvent::kMouseLeave; + return WebInputEvent::Type::kMouseLeave; case QEvent::MouseMove: case QEvent::TabletMove: - return WebInputEvent::kMouseMove; + return WebInputEvent::Type::kMouseMove; case QEvent::Wheel: - return WebInputEvent::kMouseWheel; + return WebInputEvent::Type::kMouseWheel; case QEvent::KeyPress: - return WebInputEvent::kRawKeyDown; + return WebInputEvent::Type::kRawKeyDown; case QEvent::KeyRelease: - return WebInputEvent::kKeyUp; + return WebInputEvent::Type::kKeyUp; case QEvent::HoverMove: - return WebInputEvent::kMouseMove; + return WebInputEvent::Type::kMouseMove; case QEvent::TouchBegin: - return WebInputEvent::kTouchStart; + return WebInputEvent::Type::kTouchStart; case QEvent::TouchUpdate: - return WebInputEvent::kTouchMove; + return WebInputEvent::Type::kTouchMove; case QEvent::TouchEnd: - return WebInputEvent::kTouchEnd; + return WebInputEvent::Type::kTouchEnd; case QEvent::TouchCancel: - return WebInputEvent::kTouchCancel; + return WebInputEvent::Type::kTouchCancel; default: Q_ASSERT(false); - return WebInputEvent::kMouseMove; + return WebInputEvent::Type::kMouseMove; } } @@ -1358,8 +1458,8 @@ static WebPointerProperties::PointerType pointerTypeForTabletEvent(const QTablet WebMouseEvent WebEventFactory::toWebMouseEvent(QMouseEvent *ev) { WebMouseEvent webKitEvent(webEventTypeForEvent(ev), - WebFloatPoint(ev->x(), ev->y()), - WebFloatPoint(ev->globalX(), ev->globalY()), + gfx::PointF(ev->x(), ev->y()), + gfx::PointF(ev->globalX(), ev->globalY()), mouseButtonForEvent<QMouseEvent>(ev), 0, modifiersForEvent(ev), @@ -1389,8 +1489,8 @@ WebMouseEvent WebEventFactory::toWebMouseEvent(QHoverEvent *ev) WebMouseEvent WebEventFactory::toWebMouseEvent(QTabletEvent *ev) { WebMouseEvent webKitEvent(webEventTypeForEvent(ev), - WebFloatPoint(ev->x(), ev->y()), - WebFloatPoint(ev->globalX(), ev->globalY()), + gfx::PointF(ev->x(), ev->y()), + gfx::PointF(ev->globalX(), ev->globalY()), mouseButtonForEvent<QTabletEvent>(ev), 0, modifiersForEvent(ev), @@ -1412,7 +1512,7 @@ WebMouseEvent WebEventFactory::toWebMouseEvent(QEvent *ev) WebMouseEvent webKitEvent; webKitEvent.SetTimeStamp(base::TimeTicks::Now()); - webKitEvent.SetType(WebInputEvent::kMouseLeave); + webKitEvent.SetType(WebInputEvent::Type::kMouseLeave); return webKitEvent; } @@ -1423,31 +1523,35 @@ WebGestureEvent WebEventFactory::toWebGestureEvent(QNativeGestureEvent *ev) webKitEvent.SetTimeStamp(base::TimeTicks::Now()); webKitEvent.SetModifiers(modifiersForEvent(ev)); - webKitEvent.SetPositionInWidget(WebFloatPoint(ev->localPos().x(), - ev->localPos().y())); + webKitEvent.SetPositionInWidget(gfx::PointF(ev->localPos().x(), ev->localPos().y())); - webKitEvent.SetPositionInScreen(WebFloatPoint(ev->screenPos().x(), - ev->screenPos().y())); + webKitEvent.SetPositionInScreen(gfx::PointF(ev->screenPos().x(), ev->screenPos().y())); webKitEvent.SetSourceDevice(blink::WebGestureDevice::kTouchpad); Qt::NativeGestureType gestureType = ev->gestureType(); switch (gestureType) { case Qt::ZoomNativeGesture: - webKitEvent.SetType(WebInputEvent::kGesturePinchUpdate); + webKitEvent.SetType(WebInputEvent::Type::kGesturePinchUpdate); webKitEvent.data.pinch_update.scale = static_cast<float>(ev->value() + 1.0); break; case Qt::SmartZoomNativeGesture: - webKitEvent.SetType(WebInputEvent::kGestureDoubleTap); + webKitEvent.SetType(WebInputEvent::Type::kGestureDoubleTap); webKitEvent.data.tap.tap_count = 1; break; case Qt::BeginNativeGesture: + webKitEvent.SetType(WebInputEvent::Type::kGesturePinchBegin); + webKitEvent.SetNeedsWheelEvent(true); + break; case Qt::EndNativeGesture: + webKitEvent.SetType(WebInputEvent::Type::kGesturePinchEnd); + webKitEvent.SetNeedsWheelEvent(true); + break; case Qt::RotateNativeGesture: case Qt::PanNativeGesture: case Qt::SwipeNativeGesture: // Not implemented by Chromium for now. - webKitEvent.SetType(blink::WebInputEvent::kUndefined); + webKitEvent.SetType(blink::WebInputEvent::Type::kUndefined); break; } @@ -1466,6 +1570,14 @@ static void setBlinkWheelEventDelta(blink::WebMouseWheelEvent &webEvent) webEvent.delta_y = webEvent.wheel_ticks_y * wheelScrollLines * cDefaultQtScrollStep; } +static QPoint getWheelEventDelta(const blink::WebGestureEvent &webEvent) +{ + static const float cDefaultQtScrollStep = 20.f; + static const int wheelScrollLines = QGuiApplication::styleHints()->wheelScrollLines(); + return QPoint(webEvent.data.scroll_update.delta_x * QWheelEvent::DefaultDeltasPerStep / (wheelScrollLines * cDefaultQtScrollStep), + webEvent.data.scroll_update.delta_y * QWheelEvent::DefaultDeltasPerStep / (wheelScrollLines * cDefaultQtScrollStep)); +} + blink::WebMouseWheelEvent::Phase toBlinkPhase(QWheelEvent *ev) { switch (ev->phase()) { @@ -1475,7 +1587,7 @@ blink::WebMouseWheelEvent::Phase toBlinkPhase(QWheelEvent *ev) #endif return blink::WebMouseWheelEvent::kPhaseNone; case Qt::ScrollBegin: - return ev->angleDelta().isNull() ? blink::WebMouseWheelEvent::kPhaseMayBegin : blink::WebMouseWheelEvent::kPhaseBegan; + return blink::WebMouseWheelEvent::kPhaseBegan; case Qt::ScrollUpdate: return blink::WebMouseWheelEvent::kPhaseChanged; case Qt::ScrollEnd: @@ -1505,8 +1617,9 @@ blink::WebMouseWheelEvent WebEventFactory::toWebWheelEvent(QWheelEvent *ev) webEvent.wheel_ticks_y = static_cast<float>(ev->angleDelta().y()) / QWheelEvent::DefaultDeltasPerStep; webEvent.phase = toBlinkPhase(ev); #if defined(Q_OS_DARWIN) - // has_precise_scrolling_deltas is a macOS term meaning it is a system scroll gesture, see qnsview_mouse.mm - webEvent.has_precise_scrolling_deltas = (ev->source() == Qt::MouseEventSynthesizedBySystem); + // PrecisePixel is a macOS term meaning it is a system scroll gesture, see qnsview_mouse.mm + if (ev->source() == Qt::MouseEventSynthesizedBySystem) + webEvent.delta_units = ui::ScrollGranularity::kScrollByPrecisePixel; #endif setBlinkWheelEventDelta(webEvent); @@ -1523,7 +1636,8 @@ bool WebEventFactory::coalesceWebWheelEvent(blink::WebMouseWheelEvent &webEvent, if (toBlinkPhase(ev) != webEvent.phase) return false; #if defined(Q_OS_DARWIN) - if (webEvent.has_precise_scrolling_deltas != (ev->source() == Qt::MouseEventSynthesizedBySystem)) + if ((webEvent.delta_units == ui::ScrollGranularity::kScrollByPrecisePixel) + != (ev->source() == Qt::MouseEventSynthesizedBySystem)) return false; #endif @@ -1545,6 +1659,26 @@ bool WebEventFactory::coalesceWebWheelEvent(blink::WebMouseWheelEvent &webEvent, return true; } +static QPointF toQt(gfx::PointF p) +{ + return QPointF(p.x(), p.y()); +} + +void WebEventFactory::sendUnhandledWheelEvent(const blink::WebGestureEvent &event, + RenderWidgetHostViewQtDelegate *delegate) +{ + Q_ASSERT(event.GetType() == blink::WebInputEvent::Type::kGestureScrollUpdate); + + QWheelEvent ev(toQt(event.PositionInWidget()), + toQt(event.PositionInScreen()), + QPoint(event.data.scroll_update.delta_x, event.data.scroll_update.delta_y), + getWheelEventDelta(event), + mouseButtonsForModifier(event.GetModifiers()), + keyboardModifiersForModifier(event.GetModifiers()), + Qt::NoScrollPhase, false); + delegate->unhandledWheelEvent(&ev); +} + content::NativeWebKeyboardEvent WebEventFactory::toWebKeyboardEvent(QKeyEvent *ev) { content::NativeWebKeyboardEvent webKitEvent(reinterpret_cast<gfx::NativeEvent>(ev)); @@ -1679,3 +1813,5 @@ bool WebEventFactory::getEditCommand(QKeyEvent *event, std::string *editCommand) return false; } + +} // namespace QtWebEngineCore diff --git a/src/core/web_event_factory.h b/src/core/web_event_factory.h index 526202cfb..df2f26694 100644 --- a/src/core/web_event_factory.h +++ b/src/core/web_event_factory.h @@ -42,10 +42,10 @@ #include "content/public/browser/native_web_keyboard_event.h" #ifndef QT_NO_GESTURES -#include "third_party/blink/public/platform/web_gesture_event.h" +#include "third_party/blink/public/common/input/web_gesture_event.h" #endif -#include "third_party/blink/public/platform/web_mouse_event.h" -#include "third_party/blink/public/platform/web_mouse_wheel_event.h" +#include "third_party/blink/public/common/input/web_mouse_event.h" +#include "third_party/blink/public/common/input/web_mouse_wheel_event.h" #include <QtGlobal> @@ -63,6 +63,10 @@ class QNativeGestureEvent; #endif QT_END_NAMESPACE +namespace QtWebEngineCore { + +class RenderWidgetHostViewQtDelegate; + class WebEventFactory { public: @@ -77,9 +81,11 @@ public: #endif static blink::WebMouseWheelEvent toWebWheelEvent(QWheelEvent *); static bool coalesceWebWheelEvent(blink::WebMouseWheelEvent &, QWheelEvent *); + static void sendUnhandledWheelEvent(const blink::WebGestureEvent &, RenderWidgetHostViewQtDelegate *); static content::NativeWebKeyboardEvent toWebKeyboardEvent(QKeyEvent*); static bool getEditCommand(QKeyEvent *event, std::string *editCommand); }; +} // namespace QtWebEngineCore #endif // WEB_EVENT_FACTORY_H |