diff options
Diffstat (limited to 'src/core')
104 files changed, 2788 insertions, 1611 deletions
diff --git a/src/core/api/qtwebenginecoreglobal.cpp b/src/core/api/qtwebenginecoreglobal.cpp index 072f27967..0353dac7d 100644 --- a/src/core/api/qtwebenginecoreglobal.cpp +++ b/src/core/api/qtwebenginecoreglobal.cpp @@ -85,11 +85,9 @@ QWEBENGINE_PRIVATE_EXPORT void initialize() return; } -#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 1)) // Bail out silently if the user did not construct a QGuiApplication. if (!qobject_cast<QGuiApplication *>(app)) return; -#endif if (app->thread() != QThread::currentThread()) { qFatal("QtWebEngine::initialize() must be called from the Qt gui thread."); diff --git a/src/core/api/qwebenginecallback.h b/src/core/api/qwebenginecallback.h index b967f926a..b981b2afb 100644 --- a/src/core/api/qwebenginecallback.h +++ b/src/core/api/qwebenginecallback.h @@ -92,11 +92,9 @@ private: Q_DECLARE_SHARED(QWebEngineCallback<int>) Q_DECLARE_SHARED(QWebEngineCallback<const QByteArray &>) -#if QT_VERSION >= QT_VERSION_CHECK(5,6,0) Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QWebEngineCallback<bool>) Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QWebEngineCallback<const QString &>) Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QWebEngineCallback<const QVariant &>) -#endif QT_END_NAMESPACE diff --git a/src/core/api/qwebenginecallback_p.h b/src/core/api/qwebenginecallback_p.h index b88ef4d2c..fdaf84d21 100644 --- a/src/core/api/qwebenginecallback_p.h +++ b/src/core/api/qwebenginecallback_p.h @@ -242,12 +242,10 @@ void CallbackDirectory::CallbackSharedDataPointer<T>::invokeEmpty() parent->invokeEmptyInternal(callback); } -#if QT_VERSION >= QT_VERSION_CHECK(5,6,0) #define CHECK_RELOCATABLE(x) \ Q_STATIC_ASSERT((QTypeInfoQuery<QWebEngineCallback< x > >::isRelocatable)); FOR_EACH_TYPE(CHECK_RELOCATABLE) #undef CHECK_RELOCATABLE -#endif } // namespace QtWebEngineCore diff --git a/src/core/api/qwebenginecookiestore.cpp b/src/core/api/qwebenginecookiestore.cpp index 4617882ab..6b2d542ea 100644 --- a/src/core/api/qwebenginecookiestore.cpp +++ b/src/core/api/qwebenginecookiestore.cpp @@ -229,7 +229,10 @@ QWebEngineCookieStore::~QWebEngineCookieStore() /*! Adds \a cookie to the cookie store. - It is possible to provide an optional \a origin URL argument to limit the scope of the cookie. + \note If \a cookie specifies a QNetworkCookie::domain() that does not start with a dot, + a dot is automatically prepended. To limit the cookie to the exact server, + omit QNetworkCookie::domain() and set \a origin instead. + The provided URL should also include the scheme. \note This operation is asynchronous. diff --git a/src/core/api/qwebengineurlrequestjob.cpp b/src/core/api/qwebengineurlrequestjob.cpp index e95f58863..47aab48a0 100644 --- a/src/core/api/qwebengineurlrequestjob.cpp +++ b/src/core/api/qwebengineurlrequestjob.cpp @@ -39,6 +39,7 @@ #include "qwebengineurlrequestjob.h" +#include "url_request_custom_job_proxy.h" #include "url_request_custom_job_delegate.h" using QtWebEngineCore::URLRequestCustomJobDelegate; @@ -115,6 +116,13 @@ QByteArray QWebEngineUrlRequestJob::requestMethod() const /*! Replies to the request with \a device and the MIME type \a contentType. + The user has to be aware that \a device will be used on another thread + until the job is deleted. In case simultaneous access from the main thread + is desired, the user is reponsible for making access to \a device thread-safe + for example by using QMutex. Note that the \a device object is not owned by + the web engine. Therefore, the signal QObject::destroyed() of + QWebEngineUrlRequestJob must be monitored. + The device should remain available at least as long as the job exists. When calling this method with a newly constructed device, one solution is to make the device delete itself when closed, like this: @@ -124,7 +132,7 @@ QByteArray QWebEngineUrlRequestJob::requestMethod() const */ void QWebEngineUrlRequestJob::reply(const QByteArray &contentType, QIODevice *device) { - d_ptr->setReply(contentType, device); + d_ptr->reply(contentType, device); } /*! diff --git a/src/core/api/qwebengineurlrequestjob.h b/src/core/api/qwebengineurlrequestjob.h index afa542d7e..4f23ab401 100644 --- a/src/core/api/qwebengineurlrequestjob.h +++ b/src/core/api/qwebengineurlrequestjob.h @@ -48,7 +48,7 @@ namespace QtWebEngineCore { class URLRequestCustomJobDelegate; -class URLRequestCustomJobShared; +class URLRequestCustomJobProxy; } // namespace QT_BEGIN_NAMESPACE @@ -79,7 +79,7 @@ public: private: QWebEngineUrlRequestJob(QtWebEngineCore::URLRequestCustomJobDelegate *); - friend class QtWebEngineCore::URLRequestCustomJobShared; + friend class QtWebEngineCore::URLRequestCustomJobProxy; QtWebEngineCore::URLRequestCustomJobDelegate* d_ptr; }; diff --git a/src/core/browser_accessibility_qt.cpp b/src/core/browser_accessibility_qt.cpp index 8d82f10e7..e31951307 100644 --- a/src/core/browser_accessibility_qt.cpp +++ b/src/core/browser_accessibility_qt.cpp @@ -127,7 +127,7 @@ void *BrowserAccessibilityQt::interface_cast(QAccessible::InterfaceType type) QAccessibleInterface *BrowserAccessibilityQt::parent() const { - BrowserAccessibility *p = GetParent(); + BrowserAccessibility *p = PlatformGetParent(); if (p) return static_cast<BrowserAccessibilityQt*>(p); return static_cast<BrowserAccessibilityManagerQt*>(manager())->rootParentAccessible(); @@ -160,7 +160,7 @@ QString BrowserAccessibilityQt::text(QAccessible::Text t) const case QAccessible::Value: return toQt(GetStringAttribute(ui::AX_ATTR_VALUE)); case QAccessible::Accelerator: - return toQt(GetStringAttribute(ui::AX_ATTR_SHORTCUT)); + return toQt(GetStringAttribute(ui::AX_ATTR_KEY_SHORTCUTS)); default: break; } @@ -182,38 +182,50 @@ QRect BrowserAccessibilityQt::rect() const QAccessible::Role BrowserAccessibilityQt::role() const { switch (GetRole()) { + case ui::AX_ROLE_NONE: case ui::AX_ROLE_UNKNOWN: 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 ui::AX_ROLE_WEB_AREA: + case ui::AX_ROLE_WEB_VIEW: case ui::AX_ROLE_ROOT_WEB_AREA: // not sure if we need to make a diff here, but this seems common return QAccessible::WebDocument; // These roles all directly correspond to blink accessibility roles, // keep these alphabetical. + case ui::AX_ROLE_ABBR: + return QAccessible::StaticText; case ui::AX_ROLE_ALERT: case ui::AX_ROLE_ALERT_DIALOG: return QAccessible::AlertMessage; + case ui::AX_ROLE_ANCHOR: + return QAccessible::Link; case ui::AX_ROLE_ANNOTATION: return QAccessible::StaticText; case ui::AX_ROLE_APPLICATION: return QAccessible::Document; // returning Application here makes Qt return the top level app object case ui::AX_ROLE_ARTICLE: return QAccessible::Section; + case ui::AX_ROLE_AUDIO: + return QAccessible::Sound; case ui::AX_ROLE_BANNER: return QAccessible::Section; case ui::AX_ROLE_BLOCKQUOTE: return QAccessible::Section; case ui::AX_ROLE_BUSY_INDICATOR: - return QAccessible::Animation; // FIXME + return QAccessible::NoRole; // This is unused and planned to be removed. case ui::AX_ROLE_BUTTON: return QAccessible::Button; case ui::AX_ROLE_BUTTON_DROP_DOWN: - return QAccessible::Button; + return QAccessible::ButtonDropDown; case ui::AX_ROLE_CANVAS: return QAccessible::Canvas; + case ui::AX_ROLE_CAPTION: + return QAccessible::Heading; + case ui::AX_ROLE_CARET: + return QAccessible::NoRole; // FIXME: https://codereview.chromium.org/2781613003 case ui::AX_ROLE_CELL: return QAccessible::Cell; case ui::AX_ROLE_CHECK_BOX: @@ -232,10 +244,17 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::ComplementaryContent; case ui::AX_ROLE_CONTENT_INFO: return QAccessible::Section; + case ui::AX_ROLE_DATE: + case ui::AX_ROLE_DATE_TIME: + return QAccessible::Clock; case ui::AX_ROLE_DEFINITION: return QAccessible::Paragraph; + case ui::AX_ROLE_DESCRIPTION_LIST: + return QAccessible::List; case ui::AX_ROLE_DESCRIPTION_LIST_DETAIL: return QAccessible::Paragraph; + case ui::AX_ROLE_DETAILS: + return QAccessible::Grouping; case ui::AX_ROLE_DESCRIPTION_LIST_TERM: return QAccessible::ListItem; case ui::AX_ROLE_DESKTOP: @@ -246,12 +265,18 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::NoRole; // FIXME case ui::AX_ROLE_DISCLOSURE_TRIANGLE: return QAccessible::NoRole; // FIXME - case ui::AX_ROLE_DIV: + case ui::AX_ROLE_GENERIC_CONTAINER: return QAccessible::Section; case ui::AX_ROLE_DOCUMENT: return QAccessible::Document; case ui::AX_ROLE_EMBEDDED_OBJECT: return QAccessible::Grouping; // FIXME + case ui::AX_ROLE_FEED: + return QAccessible::Section; + case ui::AX_ROLE_FIGCAPTION: + return QAccessible::Heading; + case ui::AX_ROLE_FIGURE: + return QAccessible::Section; case ui::AX_ROLE_FOOTER: return QAccessible::Footer; case ui::AX_ROLE_FORM: @@ -264,6 +289,8 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::Heading; case ui::AX_ROLE_IFRAME: return QAccessible::Grouping; + case ui::AX_ROLE_IFRAME_PRESENTATIONAL: + return QAccessible::NoRole; // FIXME case ui::AX_ROLE_IGNORED: return QAccessible::NoRole; case ui::AX_ROLE_IMAGE: @@ -274,16 +301,20 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::Link; case ui::AX_ROLE_INLINE_TEXT_BOX: return QAccessible::EditableText; + case ui::AX_ROLE_INPUT_TIME: + return QAccessible::SpinBox; case ui::AX_ROLE_LABEL_TEXT: return QAccessible::StaticText; case ui::AX_ROLE_LEGEND: - return QAccessible::NoRole; // FIXME + return QAccessible::StaticText; + case ui::AX_ROLE_LINE_BREAK: + return QAccessible::Separator; case ui::AX_ROLE_LINK: return QAccessible::Link; case ui::AX_ROLE_LIST: return QAccessible::List; case ui::AX_ROLE_LIST_BOX: - return QAccessible::List; + return QAccessible::ComboBox; case ui::AX_ROLE_LIST_BOX_OPTION: return QAccessible::ListItem; case ui::AX_ROLE_LIST_ITEM: @@ -293,11 +324,13 @@ QAccessible::Role BrowserAccessibilityQt::role() const case ui::AX_ROLE_LOCATION_BAR: return QAccessible::NoRole; // FIXME case ui::AX_ROLE_LOG: - return QAccessible::NoRole; // FIXME + return QAccessible::Section; case ui::AX_ROLE_MAIN: - return QAccessible::NoRole; // FIXME + return QAccessible::Grouping; + case ui::AX_ROLE_MARK: + return QAccessible::StaticText; case ui::AX_ROLE_MARQUEE: - return QAccessible::NoRole; // FIXME + return QAccessible::Section; case ui::AX_ROLE_MATH: return QAccessible::Equation; case ui::AX_ROLE_MENU: @@ -306,12 +339,18 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::MenuBar; case ui::AX_ROLE_MENU_ITEM: return QAccessible::MenuItem; + case ui::AX_ROLE_MENU_ITEM_CHECK_BOX: + return QAccessible::CheckBox; + case ui::AX_ROLE_MENU_ITEM_RADIO: + return QAccessible::RadioButton; case ui::AX_ROLE_MENU_BUTTON: return QAccessible::MenuItem; case ui::AX_ROLE_MENU_LIST_OPTION: return QAccessible::MenuItem; case ui::AX_ROLE_MENU_LIST_POPUP: return QAccessible::PopupMenu; + case ui::AX_ROLE_METER: + return QAccessible::Chart; case ui::AX_ROLE_NAVIGATION: return QAccessible::Section; case ui::AX_ROLE_NOTE: @@ -340,6 +379,8 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::Row; case ui::AX_ROLE_ROW_HEADER: return QAccessible::RowHeader; + case ui::AX_ROLE_RUBY: + return QAccessible::StaticText; case ui::AX_ROLE_RULER: return QAccessible::NoRole; // FIXME case ui::AX_ROLE_SCROLL_AREA: @@ -350,6 +391,8 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::NoRole; // FIXME case ui::AX_ROLE_SEARCH: return QAccessible::Section; + case ui::AX_ROLE_SEARCH_BOX: + return QAccessible::EditableText; case ui::AX_ROLE_SLIDER: return QAccessible::Slider; case ui::AX_ROLE_SLIDER_THUMB: @@ -363,9 +406,11 @@ QAccessible::Role BrowserAccessibilityQt::role() const case ui::AX_ROLE_STATIC_TEXT: return QAccessible::StaticText; case ui::AX_ROLE_STATUS: - return QAccessible::StatusBar; + return QAccessible::Indicator; case ui::AX_ROLE_SVG_ROOT: return QAccessible::Graphic; + case ui::AX_ROLE_SWITCH: + return QAccessible::Button; case ui::AX_ROLE_TABLE: return QAccessible::Table; case ui::AX_ROLE_TABLE_HEADER_CONTAINER: @@ -378,8 +423,11 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::PageTabList; case ui::AX_ROLE_TAB_PANEL: return QAccessible::PageTab; + case ui::AX_ROLE_TERM: + return QAccessible::StaticText; case ui::AX_ROLE_TEXT_FIELD: return QAccessible::EditableText; + case ui::AX_ROLE_TIME: case ui::AX_ROLE_TIMER: return QAccessible::Clock; case ui::AX_ROLE_TITLE_BAR: @@ -396,6 +444,8 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::Tree; case ui::AX_ROLE_TREE_ITEM: return QAccessible::TreeItem; + case ui::AX_ROLE_VIDEO: + return QAccessible::Animation; case ui::AX_ROLE_WINDOW: return QAccessible::Window; } @@ -408,18 +458,16 @@ QAccessible::State BrowserAccessibilityQt::state() const int32_t s = GetState(); if (s & (1 << ui::AX_STATE_BUSY)) state.busy = true; - if (s & (1 << ui::AX_STATE_CHECKED)) - state.checked = true; if (s & (1 << ui::AX_STATE_COLLAPSED)) state.collapsed = true; - if (s & (1 << ui::AX_STATE_DISABLED)) - state.disabled = true; + if (s & (1 << ui::AX_STATE_DEFAULT)) + state.defaultButton = true; + if (s & (1 << ui::AX_STATE_EDITABLE)) + state.editable = true; if (s & (1 << ui::AX_STATE_EXPANDED)) state.expanded = true; if (s & (1 << ui::AX_STATE_FOCUSABLE)) state.focusable = true; - if (manager()->GetFocus() == this) - state.focused = true; if (s & (1 << ui::AX_STATE_HASPOPUP)) state.hasPopup = true; if (s & (1 << ui::AX_STATE_HOVERED)) @@ -432,14 +480,12 @@ QAccessible::State BrowserAccessibilityQt::state() const state.multiSelectable = true; if (s & (1 << ui::AX_STATE_OFFSCREEN)) state.offscreen = true; - if (s & (1 << ui::AX_STATE_PRESSED)) - state.pressed = true; if (s & (1 << ui::AX_STATE_PROTECTED)) {} // FIXME - if (s & (1 << ui::AX_STATE_READ_ONLY)) - state.readOnly = true; if (s & (1 << ui::AX_STATE_REQUIRED)) {} // FIXME + if (s & (1 << ui::AX_STATE_RICHLY_EDITABLE)) + {} // FIXME if (s & (1 << ui::AX_STATE_SELECTABLE)) state.selectable = true; if (s & (1 << ui::AX_STATE_SELECTED)) @@ -448,8 +494,40 @@ QAccessible::State BrowserAccessibilityQt::state() const {} // FIXME if (s & (1 << ui::AX_STATE_VISITED)) {} // FIXME - if (HasState(ui::AX_STATE_EDITABLE)) - state.editable = true; + + if (manager()->GetFocus() == this) + state.focused = true; + if (HasIntAttribute(ui::AX_ATTR_CHECKED_STATE)) { + ui::AXCheckedState checkedState = (ui::AXCheckedState)GetIntAttribute(ui::AX_ATTR_CHECKED_STATE); + switch (checkedState) { + case ui::AX_CHECKED_STATE_TRUE: + if (GetRole() == ui::AX_ROLE_TOGGLE_BUTTON) + state.pressed = true; + else + state.checked = true; + break; + case ui::AX_CHECKED_STATE_MIXED: + state.checkStateMixed = true; + break; + case ui::AX_CHECKED_STATE_FALSE: + case ui::AX_CHECKED_STATE_NONE: + break; + } + } + if (HasIntAttribute(ui::AX_ATTR_RESTRICTION)) { + ui::AXRestriction restriction = (ui::AXRestriction)GetIntAttribute(ui::AX_ATTR_RESTRICTION); + switch (restriction) { + case ui::AX_RESTRICTION_READ_ONLY: + state.readOnly = true; + break; + case ui::AX_RESTRICTION_DISABLED: + state.disabled = true; + break; + case ui::AX_RESTRICTION_NONE: + break; + } + } + return state; } @@ -491,7 +569,7 @@ QStringList BrowserAccessibilityQt::keyBindingsForAction(const QString &actionNa void BrowserAccessibilityQt::addSelection(int startOffset, int endOffset) { - manager()->SetTextSelection(*this, startOffset, endOffset); + manager()->SetSelection(AXPlatformRange(CreatePositionAt(startOffset), CreatePositionAt(endOffset))); } QString BrowserAccessibilityQt::attributes(int offset, int *startOffset, int *endOffset) const @@ -549,19 +627,19 @@ QString BrowserAccessibilityQt::text(int startOffset, int endOffset) const void BrowserAccessibilityQt::removeSelection(int selectionIndex) { - manager()->SetTextSelection(*this, 0, 0); + manager()->SetSelection(AXPlatformRange(CreatePositionAt(0), CreatePositionAt(0))); } void BrowserAccessibilityQt::setCursorPosition(int position) { - manager()->SetTextSelection(*this, position, position); + manager()->SetSelection(AXPlatformRange(CreatePositionAt(position), CreatePositionAt(position))); } void BrowserAccessibilityQt::setSelection(int selectionIndex, int startOffset, int endOffset) { if (selectionIndex != 0) return; - manager()->SetTextSelection(*this, startOffset, endOffset); + manager()->SetSelection(AXPlatformRange(CreatePositionAt(startOffset), CreatePositionAt(endOffset))); } int BrowserAccessibilityQt::characterCount() const @@ -784,9 +862,9 @@ bool BrowserAccessibilityQt::isSelected() const QAccessibleInterface *BrowserAccessibilityQt::table() const { - BrowserAccessibility* find_table = GetParent(); + BrowserAccessibility* find_table = PlatformGetParent(); while (find_table && find_table->GetRole() != ui::AX_ROLE_TABLE) - find_table = find_table->GetParent(); + find_table = find_table->PlatformGetParent(); if (!find_table) return 0; return static_cast<BrowserAccessibilityQt*>(find_table); diff --git a/src/core/browser_context_adapter.cpp b/src/core/browser_context_adapter.cpp index 41b5b1932..3f8397752 100644 --- a/src/core/browser_context_adapter.cpp +++ b/src/core/browser_context_adapter.cpp @@ -41,6 +41,7 @@ #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/browsing_data_remover.h" #include "content/public/browser/download_manager.h" #include "browser_context_qt.h" @@ -194,6 +195,16 @@ void BrowserContextAdapter::cancelDownload(quint32 downloadId) downloadManagerDelegate()->cancelDownload(downloadId); } +void BrowserContextAdapter::pauseDownload(quint32 downloadId) +{ + downloadManagerDelegate()->pauseDownload(downloadId); +} + +void BrowserContextAdapter::resumeDownload(quint32 downloadId) +{ + downloadManagerDelegate()->resumeDownload(downloadId); +} + QSharedPointer<BrowserContextAdapter> BrowserContextAdapter::defaultContext() { return WebEngineContext::current()->defaultBrowserContext(); @@ -500,8 +511,10 @@ void BrowserContextAdapter::setHttpAcceptLanguage(const QString &httpAcceptLangu void BrowserContextAdapter::clearHttpCache() { - if (m_browserContext->url_request_getter_.get()) - m_browserContext->url_request_getter_->clearHttpCache(); + content::BrowsingDataRemover *remover = content::BrowserContext::GetBrowsingDataRemover(m_browserContext.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); } void BrowserContextAdapter::setSpellCheckLanguages(const QStringList &languages) diff --git a/src/core/browser_context_adapter.h b/src/core/browser_context_adapter.h index 2e7b66a7e..b647bc30c 100644 --- a/src/core/browser_context_adapter.h +++ b/src/core/browser_context_adapter.h @@ -88,6 +88,8 @@ public: void removeClient(BrowserContextAdapterClient *adapterClient); void cancelDownload(quint32 downloadId); + void pauseDownload(quint32 downloadId); + void resumeDownload(quint32 downloadId); BrowserContextQt *browserContext(); diff --git a/src/core/browser_context_adapter_client.h b/src/core/browser_context_adapter_client.h index e1fd02f96..02bee8ed6 100644 --- a/src/core/browser_context_adapter_client.h +++ b/src/core/browser_context_adapter_client.h @@ -118,6 +118,8 @@ public: QString path; int savePageFormat; bool accepted; + bool paused; + bool done; int downloadType; int downloadInterruptReason; }; diff --git a/src/core/browser_context_qt.cpp b/src/core/browser_context_qt.cpp index ffee001ff..dd0884edb 100644 --- a/src/core/browser_context_qt.cpp +++ b/src/core/browser_context_qt.cpp @@ -40,6 +40,7 @@ #include "browser_context_qt.h" #include "browser_context_adapter.h" +#include "browsing_data_remover_delegate_qt.h" #include "download_manager_delegate_qt.h" #include "permission_manager_qt.h" #include "qtwebenginecoreglobal_p.h" @@ -57,7 +58,7 @@ #include "base/base_paths.h" #include "components/prefs/pref_member.h" #include "components/prefs/pref_service.h" -#include "components/prefs/testing_pref_store.h" +#include "components/prefs/in_memory_pref_store.h" #include "components/prefs/pref_service.h" #include "components/prefs/pref_service_factory.h" #include "components/prefs/pref_registry_simple.h" @@ -72,9 +73,8 @@ namespace QtWebEngineCore { BrowserContextQt::BrowserContextQt(BrowserContextAdapter *adapter) : m_adapter(adapter), - m_prefStore(new TestingPrefStore()) + m_prefStore(new InMemoryPrefStore()) { - m_prefStore->SetInitializationCompleted(); PrefServiceFactory factory; factory.set_user_prefs(m_prefStore); scoped_refptr<PrefRegistrySimple> registry(new PrefRegistrySimple()); @@ -82,7 +82,7 @@ BrowserContextQt::BrowserContextQt(BrowserContextAdapter *adapter) #if BUILDFLAG(ENABLE_SPELLCHECK) // Initial spellcheck settings registry->RegisterStringPref(prefs::kAcceptLanguages, std::string()); - registry->RegisterListPref(spellcheck::prefs::kSpellCheckDictionaries, new base::ListValue()); + registry->RegisterListPref(spellcheck::prefs::kSpellCheckDictionaries, base::MakeUnique<base::ListValue>()); registry->RegisterStringPref(spellcheck::prefs::kSpellCheckDictionary, std::string()); registry->RegisterBooleanPref(spellcheck::prefs::kEnableSpellcheck, false); registry->RegisterBooleanPref(spellcheck::prefs::kSpellCheckUseSpellingService, false); @@ -183,6 +183,11 @@ content::BackgroundSyncController* BrowserContextQt::GetBackgroundSyncController return nullptr; } +content::BrowsingDataRemoverDelegate *BrowserContextQt::GetBrowsingDataRemoverDelegate() +{ + return new BrowsingDataRemoverDelegateQt; +} + content::PermissionManager *BrowserContextQt::GetPermissionManager() { if (!permissionManager) @@ -206,7 +211,7 @@ net::URLRequestContextGetter *BrowserContextQt::CreateRequestContextForStoragePa } #if BUILDFLAG(ENABLE_SPELLCHECK) -void BrowserContextQt::failedToLoadDictionary(const std::string &language) +void BrowserContextQt::FailedToLoadDictionary(const std::string &language) { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); qWarning() << "Could not load dictionary for:" << toQt(language) << endl @@ -229,7 +234,7 @@ QStringList BrowserContextQt::spellCheckLanguages() const QStringList spellcheck_dictionaries; for (const auto &value : *m_prefService->GetList(spellcheck::prefs::kSpellCheckDictionaries)) { std::string dictionary; - if (value->GetAsString(&dictionary)) + if (value.GetAsString(&dictionary)) spellcheck_dictionaries.append(QString::fromStdString(dictionary)); } diff --git a/src/core/browser_context_qt.h b/src/core/browser_context_qt.h index af250f506..ceb4838e3 100644 --- a/src/core/browser_context_qt.h +++ b/src/core/browser_context_qt.h @@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE class QStringList; QT_END_NAMESPACE -class TestingPrefStore; +class InMemoryPrefStore; class PrefService; namespace QtWebEngineCore { @@ -91,6 +91,7 @@ public: std::unique_ptr<content::ZoomLevelDelegate> CreateZoomLevelDelegate(const base::FilePath& partition_path) override; content::PermissionManager *GetPermissionManager() override; content::BackgroundSyncController* GetBackgroundSyncController() override; + content::BrowsingDataRemoverDelegate *GetBrowsingDataRemoverDelegate() override; // Profile implementation: PrefService* GetPrefs() override; @@ -100,7 +101,7 @@ public: BrowserContextAdapter *adapter() { return m_adapter; } #if BUILDFLAG(ENABLE_SPELLCHECK) - void failedToLoadDictionary(const std::string& language) override; + void FailedToLoadDictionary(const std::string& language) override; void setSpellCheckLanguages(const QStringList &languages); QStringList spellCheckLanguages() const; void setSpellCheckEnabled(bool enabled); @@ -115,7 +116,7 @@ private: std::unique_ptr<PermissionManagerQt> permissionManager; std::unique_ptr<SSLHostStateDelegateQt> sslHostStateDelegate; BrowserContextAdapter *m_adapter; - scoped_refptr<TestingPrefStore> m_prefStore; + scoped_refptr<InMemoryPrefStore> m_prefStore; std::unique_ptr<PrefService> m_prefService; friend class BrowserContextAdapter; diff --git a/src/core/browsing_data_remover_delegate_qt.cpp b/src/core/browsing_data_remover_delegate_qt.cpp new file mode 100644 index 000000000..aeb7a4884 --- /dev/null +++ b/src/core/browsing_data_remover_delegate_qt.cpp @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "browsing_data_remover_delegate_qt.h" + +#include "base/bind.h" +#include "components/web_cache/browser/web_cache_manager.h" +#include "content/public/browser/browsing_data_remover.h" + +#include <QtGlobal> + +namespace QtWebEngineCore { + +bool DoesOriginMatchEmbedderMask(int origin_type_mask, + const GURL &origin, + storage::SpecialStoragePolicy *policy) { + Q_UNUSED(origin_type_mask); + Q_UNUSED(origin); + Q_UNUSED(policy); + return true; +} + +content::BrowsingDataRemoverDelegate::EmbedderOriginTypeMatcher BrowsingDataRemoverDelegateQt::GetOriginTypeMatcher() const { + return base::Bind(&DoesOriginMatchEmbedderMask); +} + +bool BrowsingDataRemoverDelegateQt::MayRemoveDownloadHistory() const { + return true; +} + +void BrowsingDataRemoverDelegateQt::RemoveEmbedderData( + const base::Time &delete_begin, + const base::Time &delete_end, + int remove_mask, + const content::BrowsingDataFilterBuilder& filter_builder, + int origin_type_mask, + const base::Closure &callback) { + Q_UNUSED(delete_begin); + Q_UNUSED(delete_end); + Q_UNUSED(filter_builder); + Q_UNUSED(origin_type_mask); + + if (remove_mask & content::BrowsingDataRemover::DATA_TYPE_CACHE) + web_cache::WebCacheManager::GetInstance()->ClearCache(); + + callback.Run(); +} + +} // namespace QtWebEngineCore diff --git a/src/core/browsing_data_remover_delegate_qt.h b/src/core/browsing_data_remover_delegate_qt.h new file mode 100644 index 000000000..204f4e625 --- /dev/null +++ b/src/core/browsing_data_remover_delegate_qt.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 BROWSING_DATA_REMOVER_DELEGATE_QT_H +#define BROWSING_DATA_REMOVER_DELEGATE_QT_H + +#include "content/public/browser/browsing_data_remover_delegate.h" + +namespace QtWebEngineCore { + +class BrowsingDataRemoverDelegateQt : public content::BrowsingDataRemoverDelegate { + +public: + BrowsingDataRemoverDelegateQt() {} + ~BrowsingDataRemoverDelegateQt() override {} + + content::BrowsingDataRemoverDelegate::EmbedderOriginTypeMatcher GetOriginTypeMatcher() const override; + bool MayRemoveDownloadHistory() const override; + void RemoveEmbedderData( + const base::Time &delete_begin, + const base::Time &delete_end, + int remove_mask, + const content::BrowsingDataFilterBuilder& filter_builder, + int origin_type_mask, + const base::Closure &callback) override; +}; + +} // namespace QtWebEngineCore + +#endif // BROWSING_DATA_REMOVER_DELEGATE_QT_H diff --git a/src/core/chromium_gpu_helper.cpp b/src/core/chromium_gpu_helper.cpp index 09fe9f39e..483f68aac 100644 --- a/src/core/chromium_gpu_helper.cpp +++ b/src/core/chromium_gpu_helper.cpp @@ -65,13 +65,13 @@ base::MessageLoop *gpu_message_loop() gpu::SyncPointManager *sync_point_manager() { - gpu::GpuChannelManager *gpuChannelManager = content::GpuChildThread::instance()->ChannelManager(); + gpu::GpuChannelManager *gpuChannelManager = content::GpuChildThread::instance()->gpu_channel_manager(); return gpuChannelManager->sync_point_manager(); } gpu::gles2::MailboxManager *mailbox_manager() { - gpu::GpuChannelManager *gpuChannelManager = content::GpuChildThread::instance()->ChannelManager(); + gpu::GpuChannelManager *gpuChannelManager = content::GpuChildThread::instance()->gpu_channel_manager(); return gpuChannelManager->mailbox_manager(); } diff --git a/src/core/chromium_overrides.cpp b/src/core/chromium_overrides.cpp index 9afa80757..d1cc951d2 100644 --- a/src/core/chromium_overrides.cpp +++ b/src/core/chromium_overrides.cpp @@ -49,6 +49,9 @@ #include "content/common/font_list.h" #include "ui/base/dragdrop/os_exchange_data.h" #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 "ppapi/features/features.h" #include <QGuiApplication> #include <QScreen> @@ -96,7 +99,21 @@ XDisplay* GetQtXDisplay() { return static_cast<XDisplay*>(GLContextHelper::getXDisplay()); } -#endif + +namespace ui { +class DummyPlatformEventSource : public PlatformEventSource +{ +public: + DummyPlatformEventSource() { + DeviceDataManager::CreateInstance(); + } +}; + +std::unique_ptr<PlatformEventSource> PlatformEventSource::CreateDefault() { + return base::MakeUnique<DummyPlatformEventSource>(); +} +} // namespace ui +#endif // defined(USE_X11) namespace content { class WebContentsImpl; @@ -141,7 +158,7 @@ std::unique_ptr<base::ListValue> GetFontList_SlowBlocking() return std::move(font_list); } -#if defined(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PLUGINS) // content/browser/renderer_host/pepper/pepper_truetype_font_list.h void GetFontFamilies_SlowBlocking(std::vector<std::string> *font_families) { @@ -155,10 +172,23 @@ void GetFontsInFamily_SlowBlocking(const std::string &, std::vector<ppapi::proxy { QT_NOT_USED } -#endif //defined(ENABLE_PLUGINS) +#endif // BUILDFLAG(ENABLE_PLUGINS) } // namespace content +namespace aura { +class Window; +} + +namespace wm { +class ActivationClient; + +ActivationClient *GetActivationClient(aura::Window *) +{ + return nullptr; +} + +} // namespace wm #endif // defined(USE_AURA) || defined(USE_OZONE) std::unique_ptr<ui::OSExchangeData::Provider> @@ -170,7 +200,7 @@ ui::OSExchangeDataProviderFactory::CreateProvider() { #if defined(USE_OPENSSL_CERTS) namespace net { -scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey(X509Certificate* certificate) +scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey(const X509Certificate* certificate) { return OpenSSLClientKeyStore::GetInstance()->FetchClientCertPrivateKey(certificate); } diff --git a/src/core/clipboard_qt.cpp b/src/core/clipboard_qt.cpp index 7bf53add5..152c4db63 100644 --- a/src/core/clipboard_qt.cpp +++ b/src/core/clipboard_qt.cpp @@ -352,13 +352,20 @@ SkBitmap ClipboardQt::ReadImage(ui::ClipboardType type) const image = image.convertToFormat(QImage::Format_ARGB32); SkBitmap bitmap; - bitmap.setInfo(SkImageInfo::MakeN32(image.width(), image.height(), kOpaque_SkAlphaType)); - bitmap.setPixels(const_cast<uchar*>(image.constBits())); - // Return a deep copy of the pixel data. - SkBitmap copy; - bitmap.copyTo(©, kN32_SkColorType); - return copy; + bitmap.allocN32Pixels(image.width(), image.height(), true); + const size_t bytesPerRowDst = bitmap.rowBytes(); + const size_t bytesPerLineSrc = static_cast<size_t>(image.bytesPerLine()); + const size_t dataBytes = std::min(bytesPerRowDst, bytesPerLineSrc); + uchar *dst = static_cast<uchar *>(bitmap.getPixels()); + const uchar *src = image.constBits(); + for (int y = 0; y < image.height(); ++y) { + memcpy(dst, src, dataBytes); + dst += bytesPerRowDst; + src += bytesPerLineSrc; + } + + return bitmap; } void ClipboardQt::ReadCustomData(ui::ClipboardType clipboard_type, const base::string16& type, base::string16* result) const diff --git a/src/core/clipboard_qt.h b/src/core/clipboard_qt.h index c2ced4941..20b51a599 100644 --- a/src/core/clipboard_qt.h +++ b/src/core/clipboard_qt.h @@ -82,6 +82,8 @@ public: void ReadBookmark(base::string16* title, std::string* url) const override; void ReadData(const FormatType& format, std::string* result) const override; + virtual void OnPreShutdown() Q_DECL_OVERRIDE { } + protected: void WriteObjects(ui::ClipboardType type, const ObjectMap& objects) override; void WriteText(const char* text_data, size_t text_len) override; diff --git a/src/core/common/qt_ipc_logging.cpp b/src/core/common/qt_ipc_logging.cpp index 124124de1..f2a00b23c 100644 --- a/src/core/common/qt_ipc_logging.cpp +++ b/src/core/common/qt_ipc_logging.cpp @@ -37,9 +37,9 @@ ** ****************************************************************************/ -#include "ipc/ipc_message.h" // For IPC_MESSAGE_LOG_ENABLED +#include "ipc/ipc_features.h" // Generated buildflag header -#if defined(IPC_MESSAGE_LOG_ENABLED) +#if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED) #define IPC_MESSAGE_MACROS_LOG_ENABLED #include "content/public/common/content_ipc_logging.h" #define IPC_LOG_TABLE_ADD_ENTRY(msg_id, logger) \ diff --git a/src/core/common/qt_messages.h b/src/core/common/qt_messages.h index 239122e3f..fae80186b 100644 --- a/src/core/common/qt_messages.h +++ b/src/core/common/qt_messages.h @@ -43,11 +43,11 @@ IPC_MESSAGE_ROUTED1(WebChannelIPCTransport_Uninstall, uint /* worldId */) IPC_MESSAGE_ROUTED2(WebChannelIPCTransport_Message, std::vector<char> /*binaryJSON*/, uint /* worldId */) // User scripts messages -IPC_MESSAGE_ROUTED1(RenderViewObserverHelper_AddScript, +IPC_MESSAGE_ROUTED1(RenderFrameObserverHelper_AddScript, UserScriptData /* script */) -IPC_MESSAGE_ROUTED1(RenderViewObserverHelper_RemoveScript, +IPC_MESSAGE_ROUTED1(RenderFrameObserverHelper_RemoveScript, UserScriptData /* script */) -IPC_MESSAGE_ROUTED0(RenderViewObserverHelper_ClearScripts) +IPC_MESSAGE_ROUTED0(RenderFrameObserverHelper_ClearScripts) IPC_MESSAGE_CONTROL1(UserResourceController_AddScript, UserScriptData /* scriptContents */) IPC_MESSAGE_CONTROL1(UserResourceController_RemoveScript, UserScriptData /* scriptContents */) diff --git a/src/core/config/common.pri b/src/core/config/common.pri index b0723e333..8961e1cd3 100644 --- a/src/core/config/common.pri +++ b/src/core/config/common.pri @@ -4,46 +4,54 @@ gn_args += \ use_qt=true \ is_component_build=false \ is_shared=true \ - enable_media_router=false \ enable_nacl=false \ enable_remoting=false \ + enable_reporting=false \ enable_web_speech=false \ - use_experimental_allocator_shim=false \ + use_allocator_shim=false \ use_allocator=\"none\" \ v8_use_external_startup_data=false \ - treat_warnings_as_errors=false + treat_warnings_as_errors=false \ + enable_swiftshader=false \ + use_custom_libcxx=false -use?(printing) { - gn_args += enable_basic_printing=true enable_print_preview=true -} else { - gn_args += enable_basic_printing=false enable_print_preview=false -} +!win32: gn_args += \ + use_jumbo_build=true \ + jumbo_file_merge_limit=50 -use?(pdf) { +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 } -use?(pepper_plugins) { +qtConfig(webengine-pepper-plugins) { gn_args += enable_plugins=true enable_widevine=true } else { gn_args += enable_plugins=false enable_widevine=false } -use?(spellchecker) { +qtConfig(webengine-spellchecker) { gn_args += enable_spellcheck=true } else { gn_args += enable_spellcheck=false } -use?(webrtc) { +qtConfig(webengine-webrtc) { gn_args += enable_webrtc=true } else { gn_args += enable_webrtc=false } -use?(proprietary_codecs): gn_args += proprietary_codecs=true ffmpeg_branding=\"Chrome\" +qtConfig(webengine-proprietary-codecs): gn_args += proprietary_codecs=true ffmpeg_branding=\"Chrome\" + +precompile_header { + gn_args += enable_precompiled_headers=true +} else { + gn_args += enable_precompiled_headers=false +} CONFIG(release, debug|release) { force_debug_info { @@ -55,8 +63,24 @@ CONFIG(release, debug|release) { } } +CONFIG(debug, debug|release) { + gn_args += use_debug_fission=false +} + !webcore_debug: gn_args += remove_webcore_debug_symbols=true !v8base_debug: gn_args += remove_v8base_debug_symbols=true # Compiling with -Os makes a huge difference in binary size -contains(WEBENGINE_CONFIG, reduce_binary_size): gn_args += optimize_for_size=true +optimize_size: gn_args += optimize_for_size=true + +# We don't want to apply sanitizer options to the build tools (GN, dict convert, etc). +!host_build { + sanitizer: gn_args += sanitizer_keep_symbols=true + sanitize_address: gn_args += is_asan=true + sanitize_thread: gn_args += is_tsan=true + sanitize_memory: gn_args += is_msan=true + # rtti is required for a specific check of ubsan, -fsanitize=vptr, which uses the runtime + # type information to check that correct derived objects are assigned to base pointers. Without + # rtti, linking would fail at build time. + sanitize_undefined: gn_args += is_ubsan=true use_rtti=true +} diff --git a/src/core/config/desktop_linux.pri b/src/core/config/desktop_linux.pri index 9918e1bb2..70f1cf81e 100644 --- a/src/core/config/desktop_linux.pri +++ b/src/core/config/desktop_linux.pri @@ -3,11 +3,6 @@ include(linux.pri) gn_args += \ use_sysroot=false \ enable_session_service=false \ - enable_notifications=false \ toolkit_views=false -use?(icecc) { - gn_args += use_debug_fission=false -} - !use_gold_linker: gn_args += use_gold=false diff --git a/src/core/config/embedded_linux.pri b/src/core/config/embedded_linux.pri index d5f6d4bf5..8d9f09deb 100644 --- a/src/core/config/embedded_linux.pri +++ b/src/core/config/embedded_linux.pri @@ -6,13 +6,8 @@ gn_args += \ use_ozone=true \ use_sysroot=false \ enable_session_service=false \ - enable_notifications=false \ ozone_auto_platforms=false \ ozone_platform_headless=true \ ozone_platform_external=true \ ozone_platform=\"qt\" \ toolkit_views=false - -use?(icecc) { - gn_args += use_debug_fission=false -} diff --git a/src/core/config/linux.pri b/src/core/config/linux.pri index 831e1952c..d337f686f 100644 --- a/src/core/config/linux.pri +++ b/src/core/config/linux.pri @@ -8,17 +8,10 @@ gn_args += \ use_gio=false \ use_gnome_keyring=false \ use_kerberos=false \ - linux_use_bundled_binutils=false + linux_use_bundled_binutils=false \ + use_nss_certs=true \ + use_openssl_certs=false -use?(nss) { - gn_args += \ - use_nss_certs=true \ - use_openssl_certs=false -} else { - gn_args += \ - use_nss_certs=false \ - use_openssl_certs=true -} gcc:!clang: greaterThan(QT_GCC_MAJOR_VERSION, 5): gn_args += no_delete_null_pointer_checks=true clang { @@ -119,19 +112,33 @@ host_build { # Strip '>2 /dev/null' from $$pkgConfigExecutable() PKGCONFIG = $$first($$list($$pkgConfigExecutable())) gn_args += pkg_config=\"$$PKGCONFIG\" + PKG_CONFIG_HOST = $$(GN_PKG_CONFIG_HOST) + pkgConfigLibDir = $$(PKG_CONFIG_LIBDIR) + pkgConfigSysrootDir = $$(PKG_CONFIG_SYSROOT_DIR) + isEmpty(PKG_CONFIG_HOST): PKG_CONFIG_HOST = $$QMAKE_PKG_CONFIG_HOST + cross_compile { + !isEmpty(pkgConfigLibDir)|!isEmpty(pkgConfigSysrootDir) { + PKG_CONFIG_HOST = $$pkgConfigHostExecutable() + } + } + gn_args += host_pkg_config=\"$$PKG_CONFIG_HOST\" } - qtConfig(system-zlib): use?(system_minizip): gn_args += use_system_zlib=true use_system_minizip=true - qtConfig(system-png): gn_args += use_system_libpng=true + qtConfig(webengine-system-zlib): qtConfig(webengine-system-minizip) { + gn_args += use_system_zlib=true use_system_minizip=true + qtConfig(webengine-printing-and-pdf): gn_args += pdfium_use_system_zlib=true + } + qtConfig(webengine-system-png): gn_args += use_system_libpng=true qtConfig(system-jpeg): gn_args += use_system_libjpeg=true - use?(system_harfbuzz): gn_args += use_system_harfbuzz=true - !use?(glib): gn_args += use_glib=false - qtConfig(pulseaudio) { + qtConfig(system-freetype): gn_args += use_system_freetype=true + qtConfig(webengine-system-harfbuzz): gn_args += use_system_harfbuzz=true + qtConfig(webengine-system-glib): gn_args += use_glib=false + qtConfig(webengine-pulseaudio) { gn_args += use_pulseaudio=true } else { gn_args += use_pulseaudio=false } - qtConfig(alsa) { + qtConfig(webengine-alsa) { gn_args += use_alsa=true } else { gn_args += use_alsa=false @@ -141,15 +148,19 @@ host_build { !packagesExist(libpci): gn_args += use_libpci=false !packagesExist(xscrnsaver): gn_args += use_xscrnsaver=false - use?(system_libevent): gn_args += use_system_libevent=true - use?(system_libwebp): gn_args += use_system_libwebp=true - use?(system_libxslt): gn_args += use_system_libxml=true use_system_libxslt=true - #use?(system_jsoncpp): gn_args += use_system_jsoncpp=true - use?(system_opus): gn_args += use_system_opus=true - use?(system_snappy): gn_args += use_system_snappy=true - use?(system_vpx): gn_args += use_system_libvpx=true - use?(system_icu): gn_args += use_system_icu=true icu_use_data_file=false - use?(system_ffmpeg): gn_args += use_system_ffmpeg=true - use?(system_re2): gn_args += use_system_re2=true - #use?(system_protobuf): gn_args += use_system_protobuf=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 + + # FIXME: + #qtConfig(webengine-system-protobuf): gn_args += use_system_protobuf=true + #qtConfig(webengine-system-jsoncpp): gn_args += use_system_jsoncpp=true + #qtConfig(webengine-system-libsrtp: gn_args += use_system_libsrtp=true } diff --git a/src/core/config/mac_osx.pri b/src/core/config/mac_osx.pri index ddb397565..2d820c889 100644 --- a/src/core/config/mac_osx.pri +++ b/src/core/config/mac_osx.pri @@ -32,9 +32,9 @@ gn_args += \ toolkit_views=false \ use_external_popup_menu=false -use?(spellchecker) { - use?(native_spellchecker): gn_args += use_browser_spellchecker=true +qtConfig(webengine-spellchecker) { + qtConfig(webengine-native-spellchecker): gn_args += use_browser_spellchecker=true else: gn_args += use_browser_spellchecker=false } else { - macos: gn_args += use_browser_spellchecker=false + gn_args += use_browser_spellchecker=false } diff --git a/src/core/config/windows.pri b/src/core/config/windows.pri index db1fbd3d7..f74e0bb85 100644 --- a/src/core/config/windows.pri +++ b/src/core/config/windows.pri @@ -4,7 +4,6 @@ gn_args += \ is_clang=false \ use_sysroot=false \ use_kerberos=true \ - enable_notifications=false \ enable_session_service=false \ ninja_use_custom_environment_files=false \ is_multi_dll_chrome=false \ @@ -12,10 +11,20 @@ gn_args += \ isDeveloperBuild() { gn_args += \ - is_win_fastlink=true \ - use_incremental_linking=true + is_win_fastlink=true + + # Incremental linking doesn't work in release developer builds due to usage of /OPT:ICF + # by Chromium. + CONFIG(debug, debug|release) { + gn_args += \ + use_incremental_linking=true + } else { + gn_args += \ + use_incremental_linking=false + } } else { gn_args += \ + is_win_fastlink=false \ use_incremental_linking=false } diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index 14ec42fb7..2495e1d70 100644 --- a/src/core/content_browser_client_qt.cpp +++ b/src/core/content_browser_client_qt.cpp @@ -44,9 +44,9 @@ #include "base/threading/thread_restrictions.h" #include "components/spellcheck/spellcheck_build_features.h" #if BUILDFLAG(ENABLE_SPELLCHECK) -#include "chrome/browser/spellchecker/spellcheck_message_filter.h" +#include "chrome/browser/spellchecker/spell_check_host_impl.h" #if BUILDFLAG(USE_BROWSER_SPELLCHECKER) -#include "chrome/browser/spellchecker/spellcheck_message_filter_platform.h" +#include "components/spellcheck/browser/spellcheck_message_filter_platform.h" #endif #endif #include "content/browser/renderer_host/render_view_host_delegate.h" @@ -59,6 +59,7 @@ #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/storage_partition.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_user_data.h" #include "content/public/common/content_switches.h" @@ -68,7 +69,9 @@ #include "device/geolocation/geolocation_provider.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/binding_set.h" -#include "services/service_manager/public/cpp/interface_registry.h" +#include "net/ssl/client_cert_identity.h" +#include "services/service_manager/public/cpp/bind_source_info.h" +#include "services/service_manager/public/cpp/binder_registry.h" #include "third_party/WebKit/public/platform/modules/sensitive_input_visibility/sensitive_input_visibility_service.mojom.h" #include "ui/base/ui_base_switches.h" #include "ui/display/screen.h" @@ -111,7 +114,7 @@ #include "ui/base/resource/resource_bundle.h" #endif -#if defined(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PLUGINS) #include "content/public/browser/browser_ppapi_host.h" #include "ppapi/host/ppapi_host.h" #include "renderer_host/pepper/pepper_host_factory_qt.h" @@ -422,10 +425,6 @@ void ContentBrowserClientQt::RenderProcessWillLaunch(content::RenderProcessHost* #if BUILDFLAG(ENABLE_PEPPER_CDMS) host->AddFilter(new BrowserMessageFilterQt(id)); #endif -#if BUILDFLAG(ENABLE_SPELLCHECK) - // SpellCheckMessageFilter is required for both Hunspell and Native configurations. - host->AddFilter(new SpellCheckMessageFilter(id)); -#endif #if defined(Q_OS_MACOS) && BUILDFLAG(ENABLE_SPELLCHECK) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) host->AddFilter(new SpellCheckMessageFilterPlatform(id)); #endif @@ -466,6 +465,13 @@ content::QuotaPermissionContext *ContentBrowserClientQt::CreateQuotaPermissionCo return new QuotaPermissionContextQt; } +void ContentBrowserClientQt::GetQuotaSettings(content::BrowserContext* context, + content::StoragePartition* partition, + storage::OptionalQuotaSettingsCallback callback) +{ + storage::GetNominalDynamicSettings(partition->GetPath(), context->IsOffTheRecord(), std::move(callback)); +} + void ContentBrowserClientQt::AllowCertificateError(content::WebContents *webContents, int cert_error, const net::SSLInfo& ssl_info, @@ -484,9 +490,10 @@ void ContentBrowserClientQt::AllowCertificateError(content::WebContents *webCont void ContentBrowserClientQt::SelectClientCertificate(content::WebContents * /*webContents*/, net::SSLCertRequestInfo * /*certRequestInfo*/, + net::ClientCertIdentityList /*client_certs*/, std::unique_ptr<content::ClientCertificateDelegate> delegate) { - delegate->ContinueWithCertificate(nullptr); + delegate->ContinueWithCertificate(nullptr, nullptr); } std::string ContentBrowserClientQt::GetApplicationLocale() @@ -529,7 +536,7 @@ void ContentBrowserClientQt::GetAdditionalMappedFilesForChildProcess(const base: } #endif -#if defined(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PLUGINS) void ContentBrowserClientQt::DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host) { browser_host->GetPpapiHost()->AddHostFactoryFilter( @@ -563,16 +570,16 @@ public: return nullptr; return FromWebContents(web_contents); } - static void BindSensitiveInputVisibilityService(content::RenderFrameHost* render_frame_host, - blink::mojom::SensitiveInputVisibilityServiceRequest request) + static void BindSensitiveInputVisibilityService(blink::mojom::SensitiveInputVisibilityServiceRequest request, + content::RenderFrameHost* render_frame_host) { CreateForRenderFrameHost(render_frame_host); ServiceDriver *driver = FromRenderFrameHost(render_frame_host); if (driver) - driver->BindSensitiveInputVisibilityServiceInternal(std::move(request)); + driver->BindSensitiveInputVisibilityServiceRequest(std::move(request)); } - void BindSensitiveInputVisibilityServiceInternal(blink::mojom::SensitiveInputVisibilityServiceRequest request) + void BindSensitiveInputVisibilityServiceRequest(blink::mojom::SensitiveInputVisibilityServiceRequest request) { m_sensitiveInputVisibilityBindings.AddBinding(this, std::move(request)); } @@ -590,10 +597,77 @@ private: }; -void ContentBrowserClientQt::RegisterRenderFrameMojoInterfaces(service_manager::InterfaceRegistry* registry, - content::RenderFrameHost* render_frame_host) +void ContentBrowserClientQt::InitFrameInterfaces() +{ + m_frameInterfaces = base::MakeUnique<service_manager::BinderRegistry>(); + m_frameInterfacesParameterized = base::MakeUnique<service_manager::BinderRegistryWithArgs<content::RenderFrameHost*>>(); + m_frameInterfacesParameterized->AddInterface(base::Bind(&ServiceDriver::BindSensitiveInputVisibilityService)); +} + +void ContentBrowserClientQt::BindInterfaceRequestFromFrame(content::RenderFrameHost* render_frame_host, + const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe) +{ + if (!m_frameInterfaces.get() && !m_frameInterfacesParameterized.get()) + InitFrameInterfaces(); + + if (!m_frameInterfacesParameterized->TryBindInterface(interface_name, &interface_pipe, render_frame_host)) + m_frameInterfaces->TryBindInterface(interface_name, &interface_pipe); +} + +void ContentBrowserClientQt::ExposeInterfacesToRenderer(service_manager::BinderRegistry *registry, + content::AssociatedInterfaceRegistry */*associated_registry*/, + content::RenderProcessHost *render_process_host) { - registry->AddInterface(base::Bind(&ServiceDriver::BindSensitiveInputVisibilityService, render_frame_host)); +#if BUILDFLAG(ENABLE_SPELLCHECK) + registry->AddInterface(base::Bind(&SpellCheckHostImpl::Create, render_process_host->GetID()), + content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::UI)); +#else + Q_UNUSED(registry); + Q_UNUSED(render_process_host); +#endif +} + +bool ContentBrowserClientQt::CanCreateWindow( + content::RenderFrameHost* opener, + const GURL& opener_url, + const GURL& opener_top_level_frame_url, + const GURL& source_origin, + content::mojom::WindowContainerType container_type, + const GURL& target_url, + const content::Referrer& referrer, + const std::string& frame_name, + WindowOpenDisposition disposition, + const blink::mojom::WindowFeatures& features, + bool user_gesture, + bool opener_suppressed, + bool* no_javascript_access) { + + Q_UNUSED(opener_url); + Q_UNUSED(opener_top_level_frame_url); + Q_UNUSED(source_origin); + Q_UNUSED(container_type); + Q_UNUSED(target_url); + Q_UNUSED(referrer); + Q_UNUSED(frame_name); + Q_UNUSED(disposition); + Q_UNUSED(features); + Q_UNUSED(opener_suppressed); + + if (no_javascript_access) + *no_javascript_access = false; + + content::WebContents* webContents = content::WebContents::FromRenderFrameHost(opener); + + WebEngineSettings *settings = nullptr; + if (webContents) { + WebContentsDelegateQt* delegate = + static_cast<WebContentsDelegateQt*>(webContents->GetDelegate()); + if (delegate) + settings = delegate->webEngineSettings(); + } + + return (settings && settings->getJavaScriptCanOpenWindowsAutomatically()) || user_gesture; } } // namespace QtWebEngineCore diff --git a/src/core/content_browser_client_qt.h b/src/core/content_browser_client_qt.h index b17dd3e39..5d5a96e0c 100644 --- a/src/core/content_browser_client_qt.h +++ b/src/core/content_browser_client_qt.h @@ -42,6 +42,7 @@ #include "base/memory/ref_counted.h" #include "content/public/browser/content_browser_client.h" +#include "ppapi/features/features.h" #include <QtGlobal> @@ -53,7 +54,7 @@ namespace content { class BrowserContext; class BrowserMainParts; -#if defined(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PLUGINS) class BrowserPpapiHost; #endif @@ -65,16 +66,13 @@ class ResourceContext; class WebContentsViewPort; class WebContents; struct MainFunctionParams; +struct Referrer; } namespace gl { class GLShareGroup; } -namespace service_manager { -class InterfaceRegistry; -} - namespace QtWebEngineCore { class BrowserContextQt; class BrowserMainPartsQt; @@ -93,6 +91,9 @@ public: gl::GLShareGroup* GetInProcessGpuShareGroup() override; content::MediaObserver* GetMediaObserver() override; content::QuotaPermissionContext *CreateQuotaPermissionContext() override; + void GetQuotaSettings(content::BrowserContext *context, + content::StoragePartition *partition, + storage::OptionalQuotaSettingsCallback callback) override; void OverrideWebkitPrefs(content::RenderViewHost *, content::WebPreferences *) override; void AllowCertificateError(content::WebContents* web_contents, int cert_error, @@ -105,6 +106,7 @@ public: const base::Callback<void(content::CertificateRequestResultType)>& callback) override; void SelectClientCertificate(content::WebContents* web_contents, net::SSLCertRequestInfo* cert_request_info, + net::ClientCertIdentityList client_certs, std::unique_ptr<content::ClientCertificateDelegate> delegate) override; content::DevToolsManagerDelegate *GetDevToolsManagerDelegate() override; @@ -113,20 +115,43 @@ public: void AppendExtraCommandLineSwitches(base::CommandLine* command_line, int child_process_id) override; void GetAdditionalWebUISchemes(std::vector<std::string>* additional_schemes) override; - void RegisterRenderFrameMojoInterfaces(service_manager::InterfaceRegistry* registry, content::RenderFrameHost* render_frame_host) override; + void BindInterfaceRequestFromFrame(content::RenderFrameHost* render_frame_host, + const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe) override; + void ExposeInterfacesToRenderer(service_manager::BinderRegistry *registry, + content::AssociatedInterfaceRegistry *associated_registry, + content::RenderProcessHost *render_process_host) override; + + bool CanCreateWindow( + content::RenderFrameHost* opener, + const GURL& opener_url, + const GURL& opener_top_level_frame_url, + const GURL& source_origin, + content::mojom::WindowContainerType container_type, + const GURL& target_url, + const content::Referrer& referrer, + const std::string& frame_name, + WindowOpenDisposition disposition, + const blink::mojom::WindowFeatures& features, + bool user_gesture, + bool opener_suppressed, + bool* no_javascript_access) override; #if defined(Q_OS_LINUX) void GetAdditionalMappedFilesForChildProcess(const base::CommandLine& command_line, int child_process_id, content::FileDescriptorInfo* mappings) override; #endif -#if defined(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PLUGINS) void DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host) override; #endif private: + void InitFrameInterfaces(); BrowserMainPartsQt* m_browserMainParts; std::unique_ptr<ResourceDispatcherHostDelegateQt> 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 3d87cfd45..a3a460cb4 100644 --- a/src/core/content_client_qt.cpp +++ b/src/core/content_client_qt.cpp @@ -50,6 +50,8 @@ #include "ui/base/layout.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" + +#include "qrc_protocol_handler_qt.h" #include "type_conversion.h" #include <QCoreApplication> @@ -69,7 +71,7 @@ static QString getLocalAppDataDir() } #endif -#if defined(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PLUGINS) // The plugin logic is based on chrome/common/chrome_content_client.cc: // Copyright (c) 2012 The Chromium Authors. All rights reserved. @@ -234,6 +236,7 @@ void AddPepperWidevine(std::vector<content::PepperPluginInfo>* plugins) #elif defined(Q_OS_LINUX) pluginPaths << QStringLiteral("/opt/google/chrome/libwidevinecdmadapter.so") // Google Chrome << QStringLiteral("/usr/lib/chromium/libwidevinecdmadapter.so") // Arch + << QStringLiteral("/usr/lib/chromium-browser/libwidevinecdmadapter.so") // Ubuntu/neon << QStringLiteral("/usr/lib64/chromium/libwidevinecdmadapter.so"); // OpenSUSE style #endif } @@ -255,7 +258,7 @@ void AddPepperWidevine(std::vector<content::PepperPluginInfo>* plugins) std::vector<std::string> codecs; codecs.push_back(kCdmSupportedCodecVp8); codecs.push_back(kCdmSupportedCodecVp9); -#if defined(USE_PROPRIETARY_CODECS) +#if BUILDFLAG(USE_PROPRIETARY_CODECS) codecs.push_back(kCdmSupportedCodecAvc1); #endif // defined(USE_PROPRIETARY_CODECS) std::string codec_string = @@ -284,7 +287,7 @@ void ContentClientQt::AddPepperPlugins(std::vector<content::PepperPluginInfo>* p } } -#endif +#endif // BUILDFLAG(ENABLE_PLUGINS) #include <QCoreApplication> @@ -316,4 +319,9 @@ std::string ContentClientQt::GetProduct() const return productName.toStdString(); } +void ContentClientQt::AddAdditionalSchemes(Schemes* schemes) +{ + schemes->secure_schemes.push_back(kQrcSchemeQt); +} + } // namespace QtWebEngineCore diff --git a/src/core/content_client_qt.h b/src/core/content_client_qt.h index 7104b98b6..341406380 100644 --- a/src/core/content_client_qt.h +++ b/src/core/content_client_qt.h @@ -42,6 +42,7 @@ #include "base/strings/string_piece.h" #include "content/public/common/content_client.h" +#include "ppapi/features/features.h" #include "ui/base/layout.h" namespace QtWebEngineCore { @@ -50,9 +51,10 @@ class ContentClientQt : public content::ContentClient { public: static std::string getUserAgent(); -#if defined(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PLUGINS) void AddPepperPlugins(std::vector<content::PepperPluginInfo>* plugins) override; #endif + void AddAdditionalSchemes(Schemes* schemes) override; base::StringPiece GetDataResource(int, ui::ScaleFactor) const override; base::RefCountedMemory* GetDataResourceBytes(int resource_id) const override; diff --git a/src/core/cookie_monster_delegate_qt.cpp b/src/core/cookie_monster_delegate_qt.cpp index d2a3377a4..0fa8dead0 100644 --- a/src/core/cookie_monster_delegate_qt.cpp +++ b/src/core/cookie_monster_delegate_qt.cpp @@ -61,7 +61,7 @@ static void onSetCookieCallback(QWebEngineCookieStorePrivate *client, qint64 cal base::Bind(&QWebEngineCookieStorePrivate::onSetCallbackResult, base::Unretained(client), callbackId, success)); } -static void onDeleteCookiesCallback(QWebEngineCookieStorePrivate *client, qint64 callbackId, int numCookies) { +static void onDeleteCookiesCallback(QWebEngineCookieStorePrivate *client, qint64 callbackId, uint numCookies) { content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, base::Bind(&QWebEngineCookieStorePrivate::onDeleteCallbackResult, base::Unretained(client), callbackId, numCookies)); } @@ -96,13 +96,13 @@ void CookieMonsterDelegateQt::getAllCookies(quint64 callbackId) net::CookieMonster::GetCookieListCallback callback = base::Bind(&onGetAllCookiesCallback, m_client->d_func(), callbackId); content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, - base::Bind(&CookieMonsterDelegateQt::GetAllCookiesOnIOThread, this, callback)); + base::BindOnce(&CookieMonsterDelegateQt::GetAllCookiesOnIOThread, this, std::move(callback))); } -void CookieMonsterDelegateQt::GetAllCookiesOnIOThread(const net::CookieMonster::GetCookieListCallback& callback) +void CookieMonsterDelegateQt::GetAllCookiesOnIOThread(net::CookieMonster::GetCookieListCallback callback) { if (m_cookieMonster) - m_cookieMonster->GetAllCookiesAsync(callback); + m_cookieMonster->GetAllCookiesAsync(std::move(callback)); } void CookieMonsterDelegateQt::setCookie(quint64 callbackId, const QNetworkCookie &cookie, const QUrl &origin) @@ -117,19 +117,19 @@ void CookieMonsterDelegateQt::setCookie(quint64 callbackId, const QNetworkCookie GURL gurl = origin.isEmpty() ? sourceUrlForCookie(cookie) : toGurl(origin); content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, - base::Bind(&CookieMonsterDelegateQt::SetCookieOnIOThread, this, - gurl, cookie.toRawForm().toStdString(), callback)); + base::BindOnce(&CookieMonsterDelegateQt::SetCookieOnIOThread, this, + gurl, cookie.toRawForm().toStdString(), std::move(callback))); } void CookieMonsterDelegateQt::SetCookieOnIOThread( const GURL& url, const std::string& cookie_line, - const net::CookieMonster::SetCookiesCallback& callback) + net::CookieMonster::SetCookiesCallback callback) { net::CookieOptions options; options.set_include_httponly(); if (m_cookieMonster) - m_cookieMonster->SetCookieWithOptionsAsync(url, cookie_line, options, callback); + m_cookieMonster->SetCookieWithOptionsAsync(url, cookie_line, options, std::move(callback)); } void CookieMonsterDelegateQt::deleteCookie(const QNetworkCookie &cookie, const QUrl &origin) @@ -140,8 +140,8 @@ void CookieMonsterDelegateQt::deleteCookie(const QNetworkCookie &cookie, const Q GURL gurl = origin.isEmpty() ? sourceUrlForCookie(cookie) : toGurl(origin); content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, - base::Bind(&CookieMonsterDelegateQt::DeleteCookieOnIOThread, this, - gurl, cookie.name().toStdString())); + base::BindOnce(&CookieMonsterDelegateQt::DeleteCookieOnIOThread, this, + gurl, cookie.name().toStdString())); } void CookieMonsterDelegateQt::DeleteCookieOnIOThread(const GURL& url, const std::string& cookie_name) @@ -157,13 +157,13 @@ void CookieMonsterDelegateQt::deleteSessionCookies(quint64 callbackId) net::CookieMonster::DeleteCallback callback = base::Bind(&onDeleteCookiesCallback, m_client->d_func(), callbackId); content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, - base::Bind(&CookieMonsterDelegateQt::DeleteSessionCookiesOnIOThread, this, callback)); + base::BindOnce(&CookieMonsterDelegateQt::DeleteSessionCookiesOnIOThread, this, std::move(callback))); } -void CookieMonsterDelegateQt::DeleteSessionCookiesOnIOThread(const net::CookieMonster::DeleteCallback& callback) +void CookieMonsterDelegateQt::DeleteSessionCookiesOnIOThread(net::CookieMonster::DeleteCallback callback) { if (m_cookieMonster) - m_cookieMonster->DeleteSessionCookiesAsync(callback); + m_cookieMonster->DeleteSessionCookiesAsync(std::move(callback)); } void CookieMonsterDelegateQt::deleteAllCookies(quint64 callbackId) @@ -173,13 +173,13 @@ void CookieMonsterDelegateQt::deleteAllCookies(quint64 callbackId) net::CookieMonster::DeleteCallback callback = base::Bind(&onDeleteCookiesCallback, m_client->d_func(), callbackId); content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, - base::Bind(&CookieMonsterDelegateQt::DeleteAllOnIOThread, this, callback)); + base::BindOnce(&CookieMonsterDelegateQt::DeleteAllOnIOThread, this, std::move(callback))); } -void CookieMonsterDelegateQt::DeleteAllOnIOThread(const net::CookieMonster::DeleteCallback& callback) +void CookieMonsterDelegateQt::DeleteAllOnIOThread(net::CookieMonster::DeleteCallback callback) { if (m_cookieMonster) - m_cookieMonster->DeleteAllAsync(callback); + m_cookieMonster->DeleteAllAsync(std::move(callback)); } void CookieMonsterDelegateQt::setCookieMonster(net::CookieMonster* monster) diff --git a/src/core/cookie_monster_delegate_qt.h b/src/core/cookie_monster_delegate_qt.h index 009abdd68..4625eb264 100644 --- a/src/core/cookie_monster_delegate_qt.h +++ b/src/core/cookie_monster_delegate_qt.h @@ -86,11 +86,11 @@ public: void OnCookieChanged(const net::CanonicalCookie& cookie, bool removed, net::CookieStore::ChangeCause cause) override; private: - void GetAllCookiesOnIOThread(const net::CookieMonster::GetCookieListCallback& callback); - void SetCookieOnIOThread(const GURL& url, const std::string& cookie_line, const net::CookieMonster::SetCookiesCallback& callback); + 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(const net::CookieMonster::DeleteCallback& callback); - void DeleteAllOnIOThread(const net::CookieMonster::DeleteCallback& callback); + void DeleteSessionCookiesOnIOThread(net::CookieMonster::DeleteCallback callback); + void DeleteAllOnIOThread(net::CookieMonster::DeleteCallback callback); }; } diff --git a/src/core/core_chromium.pri b/src/core/core_chromium.pri index f13095bfe..e63199e89 100644 --- a/src/core/core_chromium.pri +++ b/src/core/core_chromium.pri @@ -28,7 +28,7 @@ RCC_DIR = $$OUT_PWD/$$getConfigDir()/.rcc # Assume that we want mobile touch and low-end hardware behaviors # whenever we are cross compiling. -contains(WEBENGINE_CONFIG, embedded_build): DEFINES += QTWEBENGINE_EMBEDDED_SWITCHES +qtConfig(webengine-embedded-build): DEFINES += QTWEBENGINE_EMBEDDED_SWITCHES qtConfig(egl): CONFIG += egl @@ -44,6 +44,7 @@ SOURCES = \ browser_context_adapter.cpp \ browser_context_adapter_client.cpp \ browser_context_qt.cpp \ + browsing_data_remover_delegate_qt.cpp \ browser_message_filter_qt.cpp \ certificate_error_controller.cpp \ chromium_gpu_helper.cpp \ @@ -79,7 +80,6 @@ SOURCES = \ qrc_protocol_handler_qt.cpp \ render_view_observer_host_qt.cpp \ render_widget_host_view_qt.cpp \ - render_widget_host_view_qt_delegate.cpp \ renderer/content_renderer_client_qt.cpp \ renderer/render_frame_observer_qt.cpp \ renderer/render_view_observer_qt.cpp \ @@ -96,6 +96,7 @@ SOURCES = \ url_request_context_getter_qt.cpp \ url_request_custom_job.cpp \ url_request_custom_job_delegate.cpp \ + url_request_custom_job_proxy.cpp \ url_request_qrc_job_qt.cpp \ user_script.cpp \ visited_links_manager_qt.cpp \ @@ -117,6 +118,7 @@ HEADERS = \ browser_context_adapter.h \ browser_context_adapter_client.h \ browser_context_qt.h \ + browsing_data_remover_delegate_qt.h \ browser_message_filter_qt.h \ certificate_error_controller_p.h \ certificate_error_controller.h \ @@ -171,6 +173,7 @@ HEADERS = \ url_request_context_getter_qt.h \ url_request_custom_job.h \ url_request_custom_job_delegate.h \ + url_request_custom_job_proxy.h \ url_request_qrc_job_qt.h \ user_script.h \ visited_links_manager_qt.h \ @@ -185,13 +188,8 @@ HEADERS = \ web_engine_settings.h \ web_event_factory.h +qtConfig(webengine-pepper-plugins) { -use?(pdf) { - SOURCES += pdfium_document_wrapper_qt.cpp - HEADERS += pdfium_document_wrapper_qt.h -} - -use?(pepper_plugins) { SOURCES += \ renderer_host/pepper/pepper_flash_browser_host_qt.cpp \ renderer_host/pepper/pepper_host_factory_qt.cpp \ @@ -207,7 +205,8 @@ use?(pepper_plugins) { renderer/pepper/pepper_renderer_host_factory_qt.h } -use?(printing) { +qtConfig(webengine-printing-and-pdf) { + SOURCES += \ printing_message_filter_qt.cpp \ print_view_manager_base_qt.cpp \ @@ -219,6 +218,10 @@ use?(printing) { print_view_manager_base_qt.h \ print_view_manager_qt.h \ renderer/print_web_view_helper_delegate_qt.h + + # pdf sources + SOURCES += pdfium_document_wrapper_qt.cpp + HEADERS += pdfium_document_wrapper_qt.h } contains(QT_CONFIG, opengl) { diff --git a/src/core/core_generator.pro b/src/core/core_generator.pro index 916c211f9..cbf126dda 100644 --- a/src/core/core_generator.pro +++ b/src/core/core_generator.pro @@ -1,3 +1,6 @@ +include($$QTWEBENGINE_OUT_ROOT/qtwebengine-config.pri) +QT_FOR_CONFIG += webengine-private + include(core_gn_config.pri) TEMPLATE = lib diff --git a/src/core/core_module.pro b/src/core/core_module.pro index 44e8ac613..d21985e60 100644 --- a/src/core/core_module.pro +++ b/src/core/core_module.pro @@ -1,3 +1,6 @@ +include($$QTWEBENGINE_OUT_ROOT/qtwebengine-config.pri) +QT_FOR_CONFIG += webengine-private + MODULE = webenginecore include(core_common.pri) @@ -37,8 +40,17 @@ 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 -linux: QMAKE_LFLAGS += -Wl,--gc-sections -Wl,-O1 -Wl,-z,now -Wl,-z,defs -else: QMAKE_LFLAGS += $$NINJA_LFLAGS + +linux { + QMAKE_LFLAGS += -Wl,--gc-sections -Wl,-O1 -Wl,-z,now + # Embedded address sanitizer symbols are undefined and are picked up by the dynamic link loader + # at runtime. Thus we do not to pass the linker flag below, because the linker would complain + # about the undefined sanitizer symbols. + !sanitizer: QMAKE_LFLAGS += -Wl,-z,defs +} else { + QMAKE_LFLAGS += $$NINJA_LFLAGS +} + POST_TARGETDEPS += $$NINJA_TARGETDEPS @@ -47,9 +59,19 @@ CONFIG *= no_smart_library_merge osx { LIBS_PRIVATE += -Wl,-force_load,$${api_library_path}$${QMAKE_DIR_SEP}lib$${api_library_name}.a } else:msvc { + !isDeveloperBuild() { + # Remove unused functions and data in debug non-developer builds, because the binaries will + # be smaller in the shipped packages. + QMAKE_LFLAGS += /OPT:REF + } else:CONFIG(debug, debug|release) { + # Make sure to override qtbase's QMAKE_LFLAGS_DEBUG option in debug developer builds, + # because qmake chooses and overrides the option when it gets appended to QMAKE_LFLAGS in + # qtbase\mkspecs\features\default_post.prf, regardless of what Chromium passes back from GN. + QMAKE_LFLAGS_DEBUG -= /DEBUG + QMAKE_LFLAGS_DEBUG += /DEBUG:FASTLINK + } # Simulate -whole-archive by passing the list of object files that belong to the public # API library as response file to the linker. - QMAKE_LFLAGS += /OPT:REF QMAKE_LFLAGS += @$${api_library_path}$${QMAKE_DIR_SEP}$${api_library_name}.lib.objects } else { LIBS_PRIVATE += -Wl,-whole-archive -l$$api_library_name -Wl,-no-whole-archive @@ -102,7 +124,7 @@ icu.files = $$OUT_PWD/$$getConfigDir()/icudtl.dat resources.path = $$[QT_INSTALL_DATA]/resources INSTALLS += locales resources - !use?(system_icu) { + !qtConfig(webengine-system-icu) { icu.CONFIG += no_check_exist icu.path = $$[QT_INSTALL_DATA]/resources INSTALLS += icu @@ -114,7 +136,7 @@ icu.files = $$OUT_PWD/$$getConfigDir()/icudtl.dat # Copy essential files to the qtbase build directory for non-prefix builds # - !use?(system_icu) { + !qtConfig(webengine-system-icu) { COPIES += icu } diff --git a/src/core/delegated_frame_node.cpp b/src/core/delegated_frame_node.cpp index 8ed88ea5d..de39300c9 100644 --- a/src/core/delegated_frame_node.cpp +++ b/src/core/delegated_frame_node.cpp @@ -59,7 +59,8 @@ #include "base/threading/thread_task_runner_handle.h" #include "cc/base/math_util.h" #include "cc/output/bsp_tree.h" -#include "cc/output/delegated_frame_data.h" +#include "cc/output/compositor_frame.h" +#include "cc/output/compositor_frame_metadata.h" #include "cc/quads/debug_border_draw_quad.h" #include "cc/quads/draw_quad.h" #include "cc/quads/render_pass_draw_quad.h" @@ -70,7 +71,7 @@ #include "cc/quads/yuv_video_draw_quad.h" #include "cc/resources/returned_resource.h" #include "cc/resources/transferable_resource.h" -#include "content/common/host_shared_bitmap_manager.h" +#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_fence.h" @@ -83,13 +84,8 @@ #include <QSGTexture> #include <private/qsgadaptationlayer_p.h> -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) #include <QSGImageNode> #include <QSGRectangleNode> -#else -#include <QSGSimpleRectNode> -#include <QSGSimpleTextureNode> -#endif #if !defined(QT_NO_EGL) #include <EGL/egl.h> @@ -211,7 +207,6 @@ protected: QVector<QSGNode*> *m_sceneGraphNodes; }; -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) class DelegatedNodeTreeUpdater : public DelegatedNodeTreeHandler { public: @@ -223,14 +218,8 @@ public: void setupRenderPassNode(QSGTexture *layer, const QRect &rect, QSGNode *) override { + Q_ASSERT(layer); QSGInternalImageNode *imageNode = static_cast<QSGInternalImageNode*>(*m_nodeIterator++); - // In case of a missing render pass, set the target rects to be empty and return early. - // cc::GLRenderer::DrawRenderPassQuad silently ignores missing render passes - if (!layer) { - imageNode->setTargetRect(QRect()); - imageNode->setInnerTargetRect(QRect()); - return; - } imageNode->setTargetRect(rect); imageNode->setInnerTargetRect(rect); imageNode->setTexture(layer); @@ -243,8 +232,11 @@ public: QSGNode *) override { QSGTextureNode *textureNode = static_cast<QSGTextureNode*>(*m_nodeIterator++); - if (textureNode->texture() != texture) + if (textureNode->texture() != texture) { textureNode->setTexture(texture); + // @TODO: This is a workaround for funky rendering, figure out why this is needed. + textureNode->markDirty(QSGTextureNode::DirtyGeometry); + } if (textureNode->textureCoordinatesTransform() != texCoordTransForm) textureNode->setTextureCoordinatesTransform(texCoordTransForm); if (textureNode->rect() != rect) @@ -258,15 +250,17 @@ public: QSGTexture::Filtering filtering, QSGNode *) override { QSGTextureNode *textureNode = static_cast<QSGTextureNode*>(*m_nodeIterator++); - + if (textureNode->texture() != texture) { + textureNode->setTexture(texture); + // @TODO: This is a workaround for funky rendering, figure out why this is needed. + textureNode->markDirty(QSGTextureNode::DirtyGeometry); + } if (textureNode->rect() != rect) textureNode->setRect(rect); if (textureNode->sourceRect() != sourceRect) textureNode->setSourceRect(sourceRect); if (textureNode->filtering() != filtering) textureNode->setFiltering(filtering); - if (textureNode->texture() != texture) - textureNode->setTexture(texture); } void setupSolidColorNode(const QRect &rect, const QColor &color, QSGNode *) override { @@ -306,7 +300,6 @@ public: private: QVector<QSGNode*>::iterator m_nodeIterator; }; -#endif class DelegatedNodeTreeCreator : public DelegatedNodeTreeHandler { @@ -321,23 +314,16 @@ public: void setupRenderPassNode(QSGTexture *layer, const QRect &rect, QSGNode *layerChain) override { + Q_ASSERT(layer); // Only QSGInternalImageNode currently supports QSGLayer textures. QSGInternalImageNode *imageNode = m_apiDelegate->createImageNode(); - layerChain->appendChildNode(imageNode); - m_sceneGraphNodes->append(imageNode); - - // In case of a missing render pass, set the target rects to be empty and return early. - // cc::GLRenderer::DrawRenderPassQuad silently ignores missing render passes - if (!layer) { - imageNode->setTargetRect(QRect()); - imageNode->setInnerTargetRect(QRect()); - return; - } - imageNode->setTargetRect(rect); imageNode->setInnerTargetRect(rect); imageNode->setTexture(layer); imageNode->update(); + + layerChain->appendChildNode(imageNode); + m_sceneGraphNodes->append(imageNode); } void setupTextureContentNode(QSGTexture *texture, const QRect &rect, const QRectF &sourceRect, @@ -437,9 +423,9 @@ private: }; -static inline QSharedPointer<QSGLayer> findRenderPassLayer(const cc::RenderPassId &id, const QVector<QPair<cc::RenderPassId, QSharedPointer<QSGLayer> > > &list) +static inline QSharedPointer<QSGLayer> findRenderPassLayer(const int &id, const QVector<QPair<int, QSharedPointer<QSGLayer> > > &list) { - typedef QPair<cc::RenderPassId, QSharedPointer<QSGLayer> > Pair; + typedef QPair<int, QSharedPointer<QSGLayer> > Pair; Q_FOREACH (const Pair &pair, list) if (pair.first == id) return pair.second; @@ -660,7 +646,7 @@ QSharedPointer<QSGTexture> ResourceHolder::initTexture(bool quadNeedsBlending, R if (!texture) { if (m_resource.is_software) { Q_ASSERT(apiDelegate); - std::unique_ptr<cc::SharedBitmap> sharedBitmap = content::HostSharedBitmapManager::current()->GetSharedBitmapFromId(m_resource.size, m_resource.mailbox_holder.mailbox); + std::unique_ptr<viz::SharedBitmap> sharedBitmap = viz::ServerSharedBitmapManager::current()->GetSharedBitmapFromId(m_resource.size, m_resource.mailbox_holder.mailbox); // 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 @@ -756,7 +742,7 @@ void DelegatedFrameNode::preprocess() #endif // Then render any intermediate RenderPass in order. - typedef QPair<cc::RenderPassId, QSharedPointer<QSGLayer> > Pair; + typedef QPair<int, QSharedPointer<QSGLayer> > Pair; Q_FOREACH (const Pair &pair, m_sgObjects.renderPassLayers) { // The layer is non-live, request a one-time update here. pair.second->scheduleUpdate(); @@ -793,8 +779,8 @@ static bool areSharedQuadStatesEqual(const cc::SharedQuadState *layerState, // 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(cc::DelegatedFrameData *frameData, - cc::DelegatedFrameData *previousFrameData) +static bool areRenderPassStructuresEqual(cc::CompositorFrame *frameData, + cc::CompositorFrame *previousFrameData) { if (!previousFrameData) return false; @@ -838,12 +824,12 @@ static bool areRenderPassStructuresEqual(cc::DelegatedFrameData *frameData, } void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, - cc::ReturnedResourceArray *resourcesToRelease, + std::vector<cc::ReturnedResource> *resourcesToRelease, RenderWidgetHostViewQtDelegate *apiDelegate) { m_chromiumCompositorData = chromiumCompositorData; - cc::DelegatedFrameData* frameData = m_chromiumCompositorData->frameData.get(); - if (!frameData) + cc::CompositorFrame* frameData = &m_chromiumCompositorData->frameData; + if (frameData->render_pass_list.empty()) return; // DelegatedFrameNode is a transform node only for the purpose of @@ -882,18 +868,12 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, // // 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. -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) - cc::DelegatedFrameData *previousFrameData = m_chromiumCompositorData->previousFrameData.get(); const bool buildNewTree = - !areRenderPassStructuresEqual(frameData, previousFrameData) || + !areRenderPassStructuresEqual(frameData, &m_chromiumCompositorData->previousFrameData) || m_sceneGraphNodes.empty() || viewportSize != m_previousViewportSize; -#else - // No updates possible with old scenegraph nodes - const bool buildNewTree = true; -#endif - m_chromiumCompositorData->previousFrameData = nullptr; + m_chromiumCompositorData->previousFrameData = cc::CompositorFrame(); SGObjects previousSGObjects; QVector<QSharedPointer<QSGTexture> > textureStrongRefs; if (buildNewTree) { @@ -905,13 +885,11 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, delete oldChain; m_sceneGraphNodes.clear(); nodeHandler.reset(new DelegatedNodeTreeCreator(&m_sceneGraphNodes, apiDelegate)); -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) } else { // Save the texture strong refs so they only go out of scope when the method returns and // the new vector of texture strong refs has been filled. qSwap(m_sgObjects.textureStrongRefs, textureStrongRefs); nodeHandler.reset(new DelegatedNodeTreeUpdater(&m_sceneGraphNodes)); -#endif } // 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. @@ -939,7 +917,7 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, } QSharedPointer<QSGRootNode> rootNode(new QSGRootNode); rpLayer->setItem(rootNode.data()); - m_sgObjects.renderPassLayers.append(QPair<cc::RenderPassId, + m_sgObjects.renderPassLayers.append(QPair<int, QSharedPointer<QSGLayer> >(pass->id, rpLayer)); m_sgObjects.renderPassRootNodes.append(rootNode); renderPassParent = rootNode.data(); @@ -1119,7 +1097,8 @@ void DelegatedFrameNode::handleQuad( QSGTexture *layer = findRenderPassLayer(renderPassQuad->render_pass_id, m_sgObjects.renderPassLayers).data(); - nodeHandler->setupRenderPassNode(layer, toQt(quad->rect), currentLayerChain); + if (layer) + nodeHandler->setupRenderPassNode(layer, toQt(quad->rect), currentLayerChain); break; } case cc::DrawQuad::TEXTURE_CONTENT: { @@ -1246,10 +1225,8 @@ ResourceHolder *DelegatedFrameNode::findAndHoldResource(unsigned resourceId, QHa void DelegatedFrameNode::holdResources(const cc::DrawQuad *quad, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates) { - auto first = quad->resources.const_begin(); - auto last = quad->resources.const_end(); - for (auto it = first; it != last; ++it) - findAndHoldResource(*it, candidates); + for (auto resource : quad->resources) + findAndHoldResource(resource, candidates); } void DelegatedFrameNode::holdResources(const cc::RenderPass *pass, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates) @@ -1274,29 +1251,22 @@ void DelegatedFrameNode::fetchAndSyncMailboxes(QList<MailboxTexture *> &mailboxe QList<gl::TransferableFence> transferredFences; { QMutexLocker lock(&m_mutex); + QVector<MailboxTexture *> mailboxesToPull; + mailboxesToPull.reserve(mailboxesToFetch.size()); gpu::SyncPointManager *syncPointManager = sync_point_manager(); - if (!m_syncPointClient) - m_syncPointClient = syncPointManager->CreateSyncPointClientWaiter(); base::MessageLoop *gpuMessageLoop = gpu_message_loop(); Q_ASSERT(m_numPendingSyncPoints == 0); m_numPendingSyncPoints = mailboxesToFetch.count(); - auto it = mailboxesToFetch.constBegin(); - auto end = mailboxesToFetch.constEnd(); - for (; it != end; ++it) { - MailboxTexture *mailboxTexture = *it; + for (MailboxTexture *mailboxTexture : qAsConst(mailboxesToFetch)) { gpu::SyncToken &syncToken = mailboxTexture->mailboxHolder().sync_token; - if (syncToken.HasData()) { - scoped_refptr<gpu::SyncPointClientState> release_state = - syncPointManager->GetSyncPointClientState(syncToken.namespace_id(), syncToken.command_buffer_id()); - if (release_state && !release_state->IsFenceSyncReleased(syncToken.release_count())) { - m_syncPointClient->WaitOutOfOrderNonThreadSafe( - release_state.get(), syncToken.release_count(), - gpuMessageLoop->task_runner(), base::Bind(&DelegatedFrameNode::pullTexture, this, mailboxTexture)); - continue; - } - } - gpuMessageLoop->task_runner()->PostTask(FROM_HERE, base::Bind(&DelegatedFrameNode::pullTexture, this, mailboxTexture)); + const auto task = base::Bind(&DelegatedFrameNode::pullTexture, this, mailboxTexture); + if (!syncPointManager->WaitOutOfOrderNonThreadSafe(syncToken, gpuMessageLoop->task_runner(), std::move(task))) + mailboxesToPull.append(mailboxTexture); + } + if (!mailboxesToPull.isEmpty()) { + auto task = base::BindOnce(&DelegatedFrameNode::pullTextures, this, std::move(mailboxesToPull)); + gpuMessageLoop->task_runner()->PostTask(FROM_HERE, std::move(task)); } m_mailboxesFetchedWaitCond.wait(&m_mutex); @@ -1372,6 +1342,25 @@ void DelegatedFrameNode::fetchAndSyncMailboxes(QList<MailboxTexture *> &mailboxe } +void DelegatedFrameNode::pullTextures(DelegatedFrameNode *frameNode, const QVector<MailboxTexture *> textures) +{ +#ifndef QT_NO_OPENGL + gpu::gles2::MailboxManager *mailboxManager = mailbox_manager(); + for (MailboxTexture *texture : textures) { + gpu::SyncToken &syncToken = texture->mailboxHolder().sync_token; + if (syncToken.HasData()) + mailboxManager->PullTextureUpdates(syncToken); + texture->fetchTexture(mailboxManager); + --frameNode->m_numPendingSyncPoints; + } + + fenceAndUnlockQt(frameNode); +#else + Q_UNUSED(frameNode) + Q_UNUSED(textures) +#endif +} + void DelegatedFrameNode::pullTexture(DelegatedFrameNode *frameNode, MailboxTexture *texture) { #ifndef QT_NO_OPENGL @@ -1380,6 +1369,18 @@ void DelegatedFrameNode::pullTexture(DelegatedFrameNode *frameNode, MailboxTextu if (syncToken.HasData()) mailboxManager->PullTextureUpdates(syncToken); texture->fetchTexture(mailboxManager); + --frameNode->m_numPendingSyncPoints; + + fenceAndUnlockQt(frameNode); +#else + Q_UNUSED(frameNode) + Q_UNUSED(texture) +#endif +} + +void DelegatedFrameNode::fenceAndUnlockQt(DelegatedFrameNode *frameNode) +{ +#ifndef QT_NO_OPENGL if (!!gl::GLContext::GetCurrent() && gl::GLFence::IsSupported()) { // Create a fence on the Chromium GPU-thread and context gl::GLFence *fence = gl::GLFence::Create(); @@ -1387,15 +1388,14 @@ void DelegatedFrameNode::pullTexture(DelegatedFrameNode *frameNode, MailboxTextu frameNode->m_textureFences.append(fence->Transfer()); delete fence; } - if (--frameNode->m_numPendingSyncPoints == 0) - base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::Bind(&DelegatedFrameNode::fenceAndUnlockQt, frameNode)); + if (frameNode->m_numPendingSyncPoints == 0) + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::Bind(&DelegatedFrameNode::unlockQt, frameNode)); #else Q_UNUSED(frameNode) - Q_UNUSED(texture) #endif } -void DelegatedFrameNode::fenceAndUnlockQt(DelegatedFrameNode *frameNode) +void DelegatedFrameNode::unlockQt(DelegatedFrameNode *frameNode) { QMutexLocker lock(&frameNode->m_mutex); // Signal preprocess() the textures are ready diff --git a/src/core/delegated_frame_node.h b/src/core/delegated_frame_node.h index e87b6abe3..4bddf4a62 100644 --- a/src/core/delegated_frame_node.h +++ b/src/core/delegated_frame_node.h @@ -40,6 +40,7 @@ #ifndef DELEGATED_FRAME_NODE_H #define DELEGATED_FRAME_NODE_H +#include "cc/output/compositor_frame.h" #include "cc/quads/render_pass.h" #include "cc/resources/transferable_resource.h" #include "gpu/command_buffer/service/sync_point_manager.h" @@ -80,8 +81,8 @@ class ChromiumCompositorData : public QSharedData { public: ChromiumCompositorData() : frameDevicePixelRatio(1) { } QHash<unsigned, QSharedPointer<ResourceHolder> > resourceHolders; - std::unique_ptr<cc::DelegatedFrameData> frameData; - std::unique_ptr<cc::DelegatedFrameData> previousFrameData; + cc::CompositorFrame frameData; + cc::CompositorFrame previousFrameData; qreal frameDevicePixelRatio; }; @@ -90,7 +91,7 @@ public: DelegatedFrameNode(); ~DelegatedFrameNode(); void preprocess(); - void commit(ChromiumCompositorData *chromiumCompositorData, cc::ReturnedResourceArray *resourcesToRelease, RenderWidgetHostViewQtDelegate *apiDelegate); + void commit(ChromiumCompositorData *chromiumCompositorData, std::vector<cc::ReturnedResource> *resourcesToRelease, RenderWidgetHostViewQtDelegate *apiDelegate); private: void flushPolygons( @@ -122,7 +123,9 @@ private: // Making those callbacks static bypasses base::Bind's ref-counting requirement // of the this pointer when the callback is a method. static void pullTexture(DelegatedFrameNode *frameNode, MailboxTexture *mailbox); + static void pullTextures(DelegatedFrameNode *frameNode, const QVector<MailboxTexture *> mailboxes); static void fenceAndUnlockQt(DelegatedFrameNode *frameNode); + static void unlockQt(DelegatedFrameNode *frameNode); ResourceHolder *findAndHoldResource(unsigned resourceId, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates); void holdResources(const cc::DrawQuad *quad, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates); @@ -131,7 +134,7 @@ private: QExplicitlySharedDataPointer<ChromiumCompositorData> m_chromiumCompositorData; struct SGObjects { - QVector<QPair<cc::RenderPassId, QSharedPointer<QSGLayer> > > renderPassLayers; + QVector<QPair<int, QSharedPointer<QSGLayer> > > renderPassLayers; QVector<QSharedPointer<QSGRootNode> > renderPassRootNodes; QVector<QSharedPointer<QSGTexture> > textureStrongRefs; } m_sgObjects; @@ -140,7 +143,6 @@ private: QWaitCondition m_mailboxesFetchedWaitCond; QMutex m_mutex; QList<gl::TransferableFence> m_textureFences; - std::unique_ptr<gpu::SyncPointClient> m_syncPointClient; #if defined(USE_X11) bool m_contextShared; QScopedPointer<QOffscreenSurface> m_offsurface; diff --git a/src/core/desktop_screen_qt.cpp b/src/core/desktop_screen_qt.cpp index 1f4c9730f..b63511c92 100644 --- a/src/core/desktop_screen_qt.cpp +++ b/src/core/desktop_screen_qt.cpp @@ -70,17 +70,18 @@ int DesktopScreenQt::GetNumDisplays() const return 0; } -std::vector<display::Display> DesktopScreenQt::GetAllDisplays() const +std::vector<display::Display>& DesktopScreenQt::GetAllDisplays() const { Q_UNREACHABLE(); - return std::vector<display::Display>(); + static std::vector<display::Display> empty; + return empty; } -display::Display DesktopScreenQt::GetDisplayNearestWindow(gfx::NativeView window) const +display::Display DesktopScreenQt::GetDisplayNearestWindow(gfx::NativeWindow window) const { // RenderViewHostImpl::OnStartDragging uses this to determine // the scale factor for the view. - return display::Display(); + return display::Display(0); } display::Display DesktopScreenQt::GetDisplayNearestPoint(const gfx::Point& point) const @@ -97,7 +98,7 @@ display::Display DesktopScreenQt::GetDisplayMatching(const gfx::Rect& match_rect display::Display DesktopScreenQt::GetPrimaryDisplay() const { - return display::Display(); + return display::Display(0); } void DesktopScreenQt::AddObserver(display::DisplayObserver* observer) diff --git a/src/core/desktop_screen_qt.h b/src/core/desktop_screen_qt.h index f052461a2..0c52c615a 100644 --- a/src/core/desktop_screen_qt.h +++ b/src/core/desktop_screen_qt.h @@ -51,8 +51,8 @@ public: 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::NativeView window) 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; diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp index 0eabd340c..40df9b3a8 100644 --- a/src/core/download_manager_delegate_qt.cpp +++ b/src/core/download_manager_delegate_qt.cpp @@ -81,7 +81,7 @@ void DownloadManagerDelegateQt::GetNextId(const content::DownloadIdCallback& cal void DownloadManagerDelegateQt::cancelDownload(const content::DownloadTargetCallback& callback) { - callback.Run(base::FilePath(), content::DownloadItem::TARGET_DISPOSITION_PROMPT, content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, base::FilePath()); + callback.Run(base::FilePath(), content::DownloadItem::TARGET_DISPOSITION_PROMPT, content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, base::FilePath(), content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED); } void DownloadManagerDelegateQt::cancelDownload(quint32 downloadId) @@ -92,6 +92,22 @@ void DownloadManagerDelegateQt::cancelDownload(quint32 downloadId) download->Cancel(/* user_cancel */ true); } +void DownloadManagerDelegateQt::pauseDownload(quint32 downloadId) +{ + content::DownloadManager* dlm = content::BrowserContext::GetDownloadManager(m_contextAdapter->browserContext()); + content::DownloadItem *download = dlm->GetDownload(downloadId); + if (download) + download->Pause(); +} + +void DownloadManagerDelegateQt::resumeDownload(quint32 downloadId) +{ + content::DownloadManager* dlm = content::BrowserContext::GetDownloadManager(m_contextAdapter->browserContext()); + content::DownloadItem *download = dlm->GetDownload(downloadId); + if (download) + download->Resume(); +} + bool DownloadManagerDelegateQt::DetermineDownloadTarget(content::DownloadItem* item, const content::DownloadTargetCallback& callback) { @@ -100,7 +116,7 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(content::DownloadItem* i // store downloads and other special downloads, so they might never end up here anyway. if (!item->GetForcedFilePath().empty()) { callback.Run(item->GetForcedFilePath(), content::DownloadItem::TARGET_DISPOSITION_PROMPT, - content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, item->GetForcedFilePath()); + content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, item->GetForcedFilePath(), content::DOWNLOAD_INTERRUPT_REASON_NONE); return true; } @@ -162,6 +178,8 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(content::DownloadItem* i suggestedFilePath, BrowserContextAdapterClient::UnknownSavePageFormat, false /* accepted */, + false /* paused */, + false /* done */, downloadType, item->GetLastReason() }; @@ -185,8 +203,11 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(content::DownloadItem* i } base::FilePath filePathForCallback(toFilePathString(suggestedFile.absoluteFilePath())); - callback.Run(filePathForCallback, content::DownloadItem::TARGET_DISPOSITION_OVERWRITE, - content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, filePathForCallback.AddExtension(toFilePathString("download"))); + callback.Run(filePathForCallback, + content::DownloadItem::TARGET_DISPOSITION_OVERWRITE, + content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, + filePathForCallback.AddExtension(toFilePathString("download")), + content::DOWNLOAD_INTERRUPT_REASON_NONE); } else cancelDownload(callback); @@ -252,6 +273,8 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content suggestedFilePath, suggestedSaveFormat, acceptedByDefault, + false, /* paused */ + false, /* done */ BrowserContextAdapterClient::SavePage, BrowserContextAdapterClient::NoReason }; @@ -290,6 +313,8 @@ void DownloadManagerDelegateQt::OnDownloadUpdated(content::DownloadItem *downloa QString(), BrowserContextAdapterClient::UnknownSavePageFormat, true /* accepted */, + download->IsPaused(), + download->IsDone(), 0 /* downloadType (unused) */, download->GetLastReason() }; diff --git a/src/core/download_manager_delegate_qt.h b/src/core/download_manager_delegate_qt.h index d23a78b0b..df43211ed 100644 --- a/src/core/download_manager_delegate_qt.h +++ b/src/core/download_manager_delegate_qt.h @@ -83,6 +83,8 @@ public: const content::SavePackagePathPickedCallback &callback) override; void cancelDownload(quint32 downloadId); + void pauseDownload(quint32 downloadId); + void resumeDownload(quint32 downloadId); void markNextDownloadAsUserRequested() { m_nextDownloadIsUserRequested = true; } diff --git a/src/core/gl_context_qt.cpp b/src/core/gl_context_qt.cpp index 8f812a9cb..cd82b1069 100644 --- a/src/core/gl_context_qt.cpp +++ b/src/core/gl_context_qt.cpp @@ -93,21 +93,20 @@ void GLContextHelper::destroy() contextHelper = 0; } -bool GLContextHelper::initializeContextOnBrowserThread(gl::GLContext* context, gl::GLSurface* surface) +bool GLContextHelper::initializeContextOnBrowserThread(gl::GLContext* context, gl::GLSurface* surface, gl::GLContextAttribs attribs) { - gl::GLContextAttribs attribs; - attribs.gpu_preference = gl::PreferDiscreteGpu; return context->Initialize(surface, attribs); } -bool GLContextHelper::initializeContext(gl::GLContext* context, gl::GLSurface* surface) +bool GLContextHelper::initializeContext(gl::GLContext* context, gl::GLSurface* surface, gl::GLContextAttribs attribs) { bool ret = false; Qt::ConnectionType connType = (QThread::currentThread() == qApp->thread()) ? Qt::DirectConnection : Qt::BlockingQueuedConnection; QMetaObject::invokeMethod(contextHelper, "initializeContextOnBrowserThread", connType, Q_RETURN_ARG(bool, ret), Q_ARG(gl::GLContext*, context), - Q_ARG(gl::GLSurface*, surface)); + Q_ARG(gl::GLSurface*, surface), + Q_ARG(gl::GLContextAttribs, attribs)); return ret; } @@ -171,7 +170,7 @@ scoped_refptr<GLContext> CreateGLContext(GLShareGroup* share_group, scoped_refptr<GLContext> context = new GLContextEGL(share_group); #endif - if (!GLContextHelper::initializeContext(context.get(), compatible_surface)) + if (!GLContextHelper::initializeContext(context.get(), compatible_surface, attribs)) return NULL; return context; diff --git a/src/core/gl_context_qt.h b/src/core/gl_context_qt.h index 47cd7dc7f..9c8a43a0a 100644 --- a/src/core/gl_context_qt.h +++ b/src/core/gl_context_qt.h @@ -41,6 +41,7 @@ #define GL_GL_CONTEXT_QT_H_ #include <QObject> +#include "ui/gl/gl_context.h" namespace gl { class GLContext; @@ -54,7 +55,7 @@ class GLContextHelper : public QObject { public: static void initialize(); static void destroy(); - static bool initializeContext(gl::GLContext* context, gl::GLSurface* surface); + static bool initializeContext(gl::GLContext* context, gl::GLSurface* surface, gl::GLContextAttribs attribs); static void* getEGLConfig(); static void* getXConfig(); @@ -63,7 +64,7 @@ public: static void* getNativeDisplay(); private: - Q_INVOKABLE bool initializeContextOnBrowserThread(gl::GLContext* context, gl::GLSurface* surface); + Q_INVOKABLE bool initializeContextOnBrowserThread(gl::GLContext* context, gl::GLSurface* surface, gl::GLContextAttribs attribs); static GLContextHelper* contextHelper; }; diff --git a/src/core/gl_surface_qt.cpp b/src/core/gl_surface_qt.cpp index 81d1b1cd5..344a4459f 100644 --- a/src/core/gl_surface_qt.cpp +++ b/src/core/gl_surface_qt.cpp @@ -103,7 +103,7 @@ public: static bool InitializeOneOff(); - bool Initialize() override; + bool Initialize(GLSurfaceFormat format) override; void Destroy() override; void* GetHandle() override; bool Resize(const gfx::Size& size, float scale_factor, bool has_alpha) override; @@ -125,7 +125,7 @@ public: explicit GLSurfacelessQtEGL(const gfx::Size& size); public: - bool Initialize() override; + bool Initialize(GLSurfaceFormat format) override; void Destroy() override; bool IsSurfaceless() const override; bool Resize(const gfx::Size& size, float scale_factor, bool has_alpha) override; @@ -153,7 +153,7 @@ public: static bool InitializeOneOff(); - bool Initialize() override; + bool Initialize(GLSurfaceFormat format) override; void Destroy() override; void* GetHandle() override; @@ -180,6 +180,16 @@ bool GLSurfaceGLX::IsCreateContextRobustnessSupported() return false; // ExtensionsContain(g_extensions, "GLX_ARB_create_context_robustness"); } +bool GLSurfaceGLX::IsEXTSwapControlSupported() +{ + return HasGLXExtension("GLX_EXT_swap_control"); +} + +bool GLSurfaceGLX::IsMESASwapControlSupported() +{ + return HasGLXExtension("GLX_MESA_swap_control"); +} + bool GLSurfaceGLX::IsCreateContextProfileSupported() { return false; // ExtensionsContain(g_extensions, "GLX_ARB_create_context_profile"); @@ -247,7 +257,7 @@ bool GLSurfaceQtGLX::InitializeOneOff() return true; } -bool GLSurfaceQtGLX::Initialize() +bool GLSurfaceQtGLX::Initialize(GLSurfaceFormat format) { Q_ASSERT(!m_surfaceBuffer); @@ -261,6 +271,7 @@ bool GLSurfaceQtGLX::Initialize() }; m_surfaceBuffer = glXCreatePbuffer(display, static_cast<GLXFBConfig>(g_config), pbuffer_attributes); + m_format = format; if (!m_surfaceBuffer) { Destroy(); @@ -297,7 +308,7 @@ public: static bool InitializeOneOff(); - bool Initialize() override; + bool Initialize(GLSurfaceFormat format) override; void Destroy() override; void *GetHandle() override; void *GetDisplay() override; @@ -327,11 +338,12 @@ bool GLSurfaceQtWGL::InitializeOneOff() return GLSurfaceWGL::InitializeOneOff(); } -bool GLSurfaceQtWGL::Initialize() +bool GLSurfaceQtWGL::Initialize(GLSurfaceFormat format) { m_surfaceBuffer = new PbufferGLSurfaceWGL(m_size); + m_format = format; - return m_surfaceBuffer->Initialize(gl::GLSurface::SURFACE_DEFAULT); + return m_surfaceBuffer->Initialize(format); } void GLSurfaceQtWGL::Destroy() @@ -426,6 +438,15 @@ bool GLSurfaceEGL::IsCreateContextWebGLCompatabilitySupported() return false; } +bool GLSurfaceEGL::IsEGLContextPrioritySupported() +{ + return false; +} + +void GLSurfaceEGL::ShutdownOneOff() +{ +} + const char* GLSurfaceEGL::GetEGLExtensions() { return g_extensions; @@ -436,6 +457,11 @@ bool GLSurfaceEGL::HasEGLExtension(const char* name) return ExtensionsContain(GetEGLExtensions(), name); } +bool GLSurfaceEGL::InitializeOneOff(EGLNativeDisplayType /*native_display*/) +{ + return GLSurfaceQtEGL::InitializeOneOff(); +} + GLSurfaceQt::GLSurfaceQt(const gfx::Size& size) : m_size(size) { @@ -456,9 +482,10 @@ GLSurfaceQtEGL::GLSurfaceQtEGL(const gfx::Size& size) { } -bool GLSurfaceQtEGL::Initialize() +bool GLSurfaceQtEGL::Initialize(GLSurfaceFormat format) { Q_ASSERT(!m_surfaceBuffer); + m_format = format; EGLDisplay display = g_display; if (!display) { @@ -513,6 +540,12 @@ gfx::Size GLSurfaceQt::GetSize() } +GLSurfaceFormat GLSurfaceQt::GetFormat() +{ + return m_format; +} + + bool GLSurfaceQtEGL::Resize(const gfx::Size& size, float scale_factor, bool has_alpha) { if (size == m_size) @@ -527,7 +560,7 @@ bool GLSurfaceQtEGL::Resize(const gfx::Size& size, float scale_factor, bool has_ m_size = size; - if (!Initialize()) { + if (!Initialize(GetFormat())) { LOG(ERROR) << "Failed to resize pbuffer."; return false; } @@ -558,8 +591,9 @@ GLSurfacelessQtEGL::GLSurfacelessQtEGL(const gfx::Size& size) { } -bool GLSurfacelessQtEGL::Initialize() +bool GLSurfacelessQtEGL::Initialize(GLSurfaceFormat format) { + m_format = format; return true; } @@ -625,7 +659,7 @@ bool usingSoftwareDynamicGL() } scoped_refptr<GLSurface> -CreateOffscreenGLSurface(const gfx::Size& size) +CreateOffscreenGLSurfaceWithFormat(const gfx::Size& size, GLSurfaceFormat format) { scoped_refptr<GLSurface> surface; switch (GetGLImplementation()) { @@ -633,13 +667,13 @@ CreateOffscreenGLSurface(const gfx::Size& size) case kGLImplementationDesktopGL: { #if defined(OS_WIN) surface = new GLSurfaceQtWGL(size); - if (surface->Initialize()) + if (surface->Initialize(format)) return surface; break; #elif defined(USE_X11) if (!g_initializedEGL) { surface = new GLSurfaceQtGLX(size); - if (surface->Initialize()) + if (surface->Initialize(format)) return surface; } // no break @@ -647,7 +681,7 @@ CreateOffscreenGLSurface(const gfx::Size& size) } case kGLImplementationEGLGLES2: { surface = new GLSurfaceQtEGL(size); - if (surface->Initialize()) + if (surface->Initialize(format)) return surface; // Surfaceless context will be used ONLY if pseudo surfaceless context @@ -655,7 +689,7 @@ CreateOffscreenGLSurface(const gfx::Size& size) // have problems. (e.g. QTBUG-57290) if (g_egl_surfaceless_context_supported) { surface = new GLSurfacelessQtEGL(size); - if (surface->Initialize()) + if (surface->Initialize(format)) return surface; } LOG(WARNING) << "Failed to create offscreen GL surface"; @@ -695,7 +729,7 @@ namespace gpu { class GpuCommandBufferStub; class GpuChannelManager; scoped_refptr<gl::GLSurface> ImageTransportSurface::CreateNativeSurface(base::WeakPtr<ImageTransportSurfaceDelegate>, - SurfaceHandle, gl::GLSurface::Format) + SurfaceHandle, gl::GLSurfaceFormat) { QT_NOT_USED return scoped_refptr<gl::GLSurface>(); diff --git a/src/core/gl_surface_qt.h b/src/core/gl_surface_qt.h index 08b501846..c26cb7ed0 100644 --- a/src/core/gl_surface_qt.h +++ b/src/core/gl_surface_qt.h @@ -59,12 +59,14 @@ public: bool IsOffscreen() override; gfx::SwapResult SwapBuffers() override; gfx::Size GetSize() override; + GLSurfaceFormat GetFormat() override; protected: GLSurfaceQt(); virtual ~GLSurfaceQt(); gfx::Size m_size; + GLSurfaceFormat m_format; private: DISALLOW_COPY_AND_ASSIGN(GLSurfaceQt); diff --git a/src/core/gn_run.pro b/src/core/gn_run.pro index ee4e7892e..dbf859100 100644 --- a/src/core/gn_run.pro +++ b/src/core/gn_run.pro @@ -1,13 +1,11 @@ -isQtMinimum(5, 8) { - include($$QTWEBENGINE_OUT_ROOT/qtwebengine-config.pri) - QT_FOR_CONFIG += webengine-private -} +include($$QTWEBENGINE_OUT_ROOT/qtwebengine-config.pri) +QT_FOR_CONFIG += webengine webengine-private TEMPLATE = aux qtConfig(debug_and_release): CONFIG += debug_and_release build_all -qtConfig(system-ninja) { +qtConfig(webengine-system-ninja) { QT_TOOL.ninja.binary = ninja } else { QT_TOOL.ninja.binary = $$shell_quote($$shell_path($$ninjaPath())) @@ -37,7 +35,7 @@ build_pass|!debug_and_release { gn_args += "qtwebengine_target=\"$$system_path($$OUT_PWD/$$getConfigDir()):QtWebEngineCore\"" - !qtConfig(system-gn) { + !qtConfig(webengine-system-gn) { gn_binary = $$system_quote($$system_path($$gnPath())) } diff --git a/src/core/javascript_dialog_manager_qt.cpp b/src/core/javascript_dialog_manager_qt.cpp index 5fac12dd3..a1a8604a4 100644 --- a/src/core/javascript_dialog_manager_qt.cpp +++ b/src/core/javascript_dialog_manager_qt.cpp @@ -48,14 +48,17 @@ namespace QtWebEngineCore { -Q_STATIC_ASSERT_X(static_cast<int>(content::JAVASCRIPT_MESSAGE_TYPE_PROMPT) == static_cast<int>(WebContentsAdapterClient::PromptDialog), "These enums should be in sync."); +ASSERT_ENUMS_MATCH(content::JAVASCRIPT_DIALOG_TYPE_ALERT, WebContentsAdapterClient::AlertDialog) +ASSERT_ENUMS_MATCH(content::JAVASCRIPT_DIALOG_TYPE_CONFIRM, WebContentsAdapterClient::ConfirmDialog) +ASSERT_ENUMS_MATCH(content::JAVASCRIPT_DIALOG_TYPE_PROMPT, WebContentsAdapterClient::PromptDialog) + JavaScriptDialogManagerQt *JavaScriptDialogManagerQt::GetInstance() { return base::Singleton<JavaScriptDialogManagerQt>::get(); } -void JavaScriptDialogManagerQt::RunJavaScriptDialog(content::WebContents *webContents, const GURL &originUrl, content::JavaScriptMessageType javascriptMessageType, const base::string16 &messageText, const base::string16 &defaultPromptText, const content::JavaScriptDialogManager::DialogClosedCallback &callback, bool *didSuppressMessage) +void JavaScriptDialogManagerQt::RunJavaScriptDialog(content::WebContents *webContents, const GURL &originUrl, content::JavaScriptDialogType dialog_type, const base::string16 &messageText, const base::string16 &defaultPromptText, const content::JavaScriptDialogManager::DialogClosedCallback &callback, bool *didSuppressMessage) { WebContentsAdapterClient *client = WebContentsViewQt::from(static_cast<content::WebContentsImpl*>(webContents)->GetView())->client(); if (!client) { @@ -64,7 +67,7 @@ void JavaScriptDialogManagerQt::RunJavaScriptDialog(content::WebContents *webCon return; } - WebContentsAdapterClient::JavascriptDialogType dialogType = static_cast<WebContentsAdapterClient::JavascriptDialogType>(javascriptMessageType); + WebContentsAdapterClient::JavascriptDialogType dialogType = static_cast<WebContentsAdapterClient::JavascriptDialogType>(dialog_type); runDialogForContents(webContents, dialogType, toQt(messageText).toHtmlEscaped(), toQt(defaultPromptText).toHtmlEscaped(), toQt(originUrl.GetOrigin()), callback); } diff --git a/src/core/javascript_dialog_manager_qt.h b/src/core/javascript_dialog_manager_qt.h index ad2a54cac..291f027a9 100644 --- a/src/core/javascript_dialog_manager_qt.h +++ b/src/core/javascript_dialog_manager_qt.h @@ -40,7 +40,6 @@ #define JAVASCRIPT_DIALOG_MANAGER_QT_H #include "content/public/browser/javascript_dialog_manager.h" -#include "content/public/common/javascript_message_type.h" #include "web_contents_adapter_client.h" @@ -60,13 +59,15 @@ public: // For use with the Singleton helper class from chromium static JavaScriptDialogManagerQt *GetInstance(); - void RunJavaScriptDialog(content::WebContents *, const GURL &, content::JavaScriptMessageType javascriptMessageType, + void RunJavaScriptDialog(content::WebContents *, const GURL &, content::JavaScriptDialogType dialog_type, const base::string16 &messageText, const base::string16 &defaultPromptText, - const content::JavaScriptDialogManager::DialogClosedCallback &callback, bool *didSuppressMessage) override; + const content::JavaScriptDialogManager::DialogClosedCallback &callback, + bool *didSuppressMessage) override; - void RunBeforeUnloadDialog(content::WebContents *, bool isReload, const content::JavaScriptDialogManager::DialogClosedCallback &callback) override; + void RunBeforeUnloadDialog(content::WebContents *, bool isReload, + const content::JavaScriptDialogManager::DialogClosedCallback &callback) override; bool HandleJavaScriptDialog(content::WebContents *, bool accept, const base::string16 *promptOverride) override; - void CancelDialogs(content::WebContents *contents, bool /*suppress_callbacks*/, bool /*reset_state*/) override + void CancelDialogs(content::WebContents *contents, bool /*reset_state*/) override { takeDialogForContents(contents); } diff --git a/src/core/media_capture_devices_dispatcher.cpp b/src/core/media_capture_devices_dispatcher.cpp index 105e85ec6..87fe543b1 100644 --- a/src/core/media_capture_devices_dispatcher.cpp +++ b/src/core/media_capture_devices_dispatcher.cpp @@ -62,9 +62,13 @@ #include "content/public/common/media_stream_request.h" #include "media/audio/audio_device_description.h" #include "media/audio/audio_manager_base.h" +#include "media/media_features.h" +#include "ui/base/l10n/l10n_util.h" + +#if BUILDFLAG(ENABLE_WEBRTC) #include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h" #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h" -#include "ui/base/l10n/l10n_util.h" +#endif #include <QtCore/qcoreapplication.h> @@ -117,13 +121,51 @@ std::unique_ptr<content::MediaStreamUI> getDevicesForDesktopCapture(content::Med return std::move(ui); } +content::DesktopMediaID getDefaultScreenId() +{ +#if BUILDFLAG(ENABLE_WEBRTC) + // Source id patterns are different across platforms. + // On Linux, the hardcoded value "0" is used. + // 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. + // The code is based on the file + // src/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc. + webrtc::DesktopCaptureOptions options = + webrtc::DesktopCaptureOptions::CreateDefault(); + options.set_disable_effects(false); + std::unique_ptr<webrtc::DesktopCapturer> screen_capturer( + webrtc::DesktopCapturer::CreateScreenCapturer(options)); + + if (screen_capturer) { + webrtc::DesktopCapturer::SourceList screens; + if (screen_capturer->GetSourceList(&screens)) { + if (screens.size() > 0) { + return content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, screens[0].id); + } + } + } +#endif + + return content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, 0); +} + WebContentsAdapterClient::MediaRequestFlags mediaRequestFlagsForRequest(const content::MediaStreamRequest &request) { WebContentsAdapterClient::MediaRequestFlags requestFlags = WebContentsAdapterClient::MediaNone; + if (request.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE) requestFlags |= WebContentsAdapterClient::MediaAudioCapture; + else if (request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE) + requestFlags |= WebContentsAdapterClient::MediaDesktopAudioCapture; + if (request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE) requestFlags |= WebContentsAdapterClient::MediaVideoCapture; + else if (request.video_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE) + requestFlags |= WebContentsAdapterClient::MediaDesktopVideoCapture; + return requestFlags; } @@ -146,6 +188,7 @@ void MediaCaptureDevicesDispatcher::handleMediaAccessPermissionResponse(content: { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + std::unique_ptr<content::MediaStreamUI> ui; content::MediaStreamDevices devices; std::map<content::WebContents*, RequestsQueue>::iterator it = m_pendingRequests.find(webContents); @@ -172,16 +215,30 @@ void MediaCaptureDevicesDispatcher::handleMediaAccessPermissionResponse(content: (request.audio_type && authorizationFlags & WebContentsAdapterClient::MediaAudioCapture); bool webcamRequested = (request.video_type && authorizationFlags & WebContentsAdapterClient::MediaVideoCapture); - if (securityOriginsMatch && (microphoneRequested || webcamRequested)) { - switch (request.request_type) { - case content::MEDIA_OPEN_DEVICE_PEPPER_ONLY: - getDefaultDevices("", "", microphoneRequested, webcamRequested, &devices); - break; - case content::MEDIA_DEVICE_ACCESS: - case content::MEDIA_GENERATE_STREAM: - getDefaultDevices(request.requested_audio_device_id, request.requested_video_device_id, - microphoneRequested, webcamRequested, &devices); - break; + bool desktopAudioRequested = + (request.audio_type && authorizationFlags & WebContentsAdapterClient::MediaDesktopAudioCapture); + bool desktopVideoRequested = + (request.video_type && authorizationFlags & WebContentsAdapterClient::MediaDesktopVideoCapture); + + if (securityOriginsMatch) { + if (microphoneRequested || webcamRequested) { + switch (request.request_type) { + case content::MEDIA_OPEN_DEVICE_PEPPER_ONLY: + getDefaultDevices("", "", microphoneRequested, webcamRequested, &devices); + break; + case content::MEDIA_DEVICE_ACCESS: + case content::MEDIA_GENERATE_STREAM: + getDefaultDevices(request.requested_audio_device_id, request.requested_video_device_id, + microphoneRequested, webcamRequested, &devices); + break; + } + } else if (desktopVideoRequested) { + ui = getDevicesForDesktopCapture( + &devices, + getDefaultScreenId(), + desktopAudioRequested, + /* display_notification: */ false, + getContentsUrl(webContents)); } } @@ -196,7 +253,7 @@ void MediaCaptureDevicesDispatcher::handleMediaAccessPermissionResponse(content: BrowserThread::UI, FROM_HERE, base::Bind(&MediaCaptureDevicesDispatcher::ProcessQueuedAccessRequest, base::Unretained(this), webContents)); } - callback.Run(devices, devices.empty() ? content::MEDIA_DEVICE_INVALID_STATE : content::MEDIA_DEVICE_OK, std::unique_ptr<content::MediaStreamUI>()); + callback.Run(devices, devices.empty() ? content::MEDIA_DEVICE_INVALID_STATE : content::MEDIA_DEVICE_OK, std::move(ui)); } @@ -234,22 +291,34 @@ void MediaCaptureDevicesDispatcher::processMediaAccessRequest(WebContentsAdapter , const content::MediaStreamRequest &request , const content::MediaResponseCallback &callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - // Let's not support tab capture for now. - if (request.video_type == content::MEDIA_TAB_VIDEO_CAPTURE || request.audio_type == content::MEDIA_TAB_AUDIO_CAPTURE) - return; - - if (request.video_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE || request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE) - // It's still unclear what to make of screen capture. We can rely on existing javascript dialog infrastructure - // to experiment with this without exposing it through our API yet. - processDesktopCaptureAccessRequest(webContents, request, callback); - else { - enqueueMediaAccessRequest(webContents, request, callback); - // We might not require this approval for pepper requests. - adapterClient->runMediaAccessPermissionRequest(toQt(request.security_origin), mediaRequestFlagsForRequest(request)); - } + // Let's not support tab capture for now. + if (request.video_type == content::MEDIA_TAB_VIDEO_CAPTURE || request.audio_type == content::MEDIA_TAB_AUDIO_CAPTURE) { + callback.Run(content::MediaStreamDevices(), content::MEDIA_DEVICE_NOT_SUPPORTED, std::unique_ptr<content::MediaStreamUI>()); + return; + } + if (request.video_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE || + request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE) { + const bool screenCaptureEnabled = + adapterClient->webEngineSettings()->testAttribute(WebEngineSettings::ScreenCaptureEnabled); + const bool originIsSecure = content::IsOriginSecure(request.security_origin); + if (!screenCaptureEnabled || !originIsSecure) { + callback.Run(content::MediaStreamDevices(), content::MEDIA_DEVICE_INVALID_STATE, std::unique_ptr<content::MediaStreamUI>()); + return; + } + + if (!request.requested_video_device_id.empty()) { + // Non-empty device id from the chooseDesktopMedia() extension API. + processDesktopCaptureAccessRequest(webContents, request, callback); + return; + } + } + + enqueueMediaAccessRequest(webContents, request, callback); + // We might not require this approval for pepper requests. + adapterClient->runMediaAccessPermissionRequest(toQt(request.security_origin), mediaRequestFlagsForRequest(request)); } void MediaCaptureDevicesDispatcher::processDesktopCaptureAccessRequest(content::WebContents *webContents, const content::MediaStreamRequest &request @@ -258,19 +327,12 @@ void MediaCaptureDevicesDispatcher::processDesktopCaptureAccessRequest(content:: content::MediaStreamDevices devices; std::unique_ptr<content::MediaStreamUI> ui; - if (request.video_type != content::MEDIA_DESKTOP_VIDEO_CAPTURE) { + if (request.video_type != content::MEDIA_DESKTOP_VIDEO_CAPTURE || + request.requested_video_device_id.empty()) { callback.Run(devices, content::MEDIA_DEVICE_INVALID_STATE, std::move(ui)); return; } - // If the device id wasn't specified then this is a screen capture request - // (i.e. chooseDesktopMedia() API wasn't used to generate device id). - if (request.requested_video_device_id.empty()) { - processScreenCaptureAccessRequest( - webContents, request, callback); - return; - } - content::WebContents* const web_contents_for_stream = content::WebContents::FromRenderFrameHost( content::RenderFrameHost::FromID(request.render_process_id, request.render_frame_id)); content::RenderFrameHost* const main_frame = web_contents_for_stream ? web_contents_for_stream->GetMainFrame() : NULL; @@ -303,84 +365,6 @@ void MediaCaptureDevicesDispatcher::processDesktopCaptureAccessRequest(content:: callback.Run(devices, devices.empty() ? content::MEDIA_DEVICE_INVALID_STATE : content::MEDIA_DEVICE_OK, std::move(ui)); } -void MediaCaptureDevicesDispatcher::processScreenCaptureAccessRequest(content::WebContents *webContents, const content::MediaStreamRequest &request - ,const content::MediaResponseCallback &callback) -{ - DCHECK_EQ(request.video_type, content::MEDIA_DESKTOP_VIDEO_CAPTURE); - - WebContentsAdapterClient *adapterClient = WebContentsViewQt::from(static_cast<content::WebContentsImpl*>(webContents)->GetView())->client(); - const bool screenCaptureEnabled = adapterClient->webEngineSettings()->testAttribute(WebEngineSettings::ScreenCaptureEnabled); - - const bool originIsSecure = content::IsOriginSecure(request.security_origin); - - if (screenCaptureEnabled && originIsSecure) { - - enqueueMediaAccessRequest(webContents, request, callback); - base::Callback<void(bool, const base::string16&)> dialogCallback = base::Bind(&MediaCaptureDevicesDispatcher::handleScreenCaptureAccessRequest, - base::Unretained(this), base::Unretained(webContents)); - - QUrl securityOrigin(toQt(request.security_origin)); - QString message = QCoreApplication::translate("MediaCaptureDevicesDispatcher", "Do you want %1 to share your screen?").arg(securityOrigin.toString()); - QString title = QCoreApplication::translate("MediaCaptureDevicesDispatcher", "%1 Screen Sharing request").arg(securityOrigin.toString()); - JavaScriptDialogManagerQt::GetInstance()->runDialogForContents(webContents, WebContentsAdapterClient::InternalAuthorizationDialog, message - , QString(), securityOrigin, dialogCallback, title); - } else - callback.Run(content::MediaStreamDevices(), content::MEDIA_DEVICE_INVALID_STATE, std::unique_ptr<content::MediaStreamUI>()); -} - -void MediaCaptureDevicesDispatcher::handleScreenCaptureAccessRequest(content::WebContents *webContents, bool userAccepted, const base::string16 &) -{ - content::MediaStreamDevices devices; - std::unique_ptr<content::MediaStreamUI> ui; - if (userAccepted) { - // Source id patterns are different across platforms. - // On Linux, the hardcoded value "0" is used. - // On Windows, the screens are enumerated consecutively in increasing order from 0. - // On macOS the source ids are randomish numbers assigned by the OS. - webrtc::DesktopCapturer::SourceId id = 0; - -#if defined(ENABLE_WEBRTC) - // 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. - // The code is based on the file - // src/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc. - webrtc::DesktopCaptureOptions options = - webrtc::DesktopCaptureOptions::CreateDefault(); - options.set_disable_effects(false); - std::unique_ptr<webrtc::DesktopCapturer> screen_capturer( - webrtc::DesktopCapturer::CreateScreenCapturer(options)); - - if (screen_capturer) { - webrtc::DesktopCapturer::SourceList screens; - if (screen_capturer->GetSourceList(&screens)) { - if (screens.size() > 0) { - id = screens[0].id; - } - } - } -#endif - - content::DesktopMediaID screenId = content::DesktopMediaID( - content::DesktopMediaID::TYPE_SCREEN, id); - ui = getDevicesForDesktopCapture(&devices, screenId, false/*capture_audio*/, false/*display_notification*/, getContentsUrl(webContents)); - } - std::map<content::WebContents*, RequestsQueue>::iterator it = - m_pendingRequests.find(webContents); - if (it == m_pendingRequests.end()) { - // WebContents has been destroyed. Don't need to do anything. - return; - } - - RequestsQueue &queue(it->second); - if (queue.empty()) - return; - - content::MediaResponseCallback callback = queue.front().callback; - queue.pop_front(); - - callback.Run(devices, devices.empty() ? content::MEDIA_DEVICE_INVALID_STATE : content::MEDIA_DEVICE_OK, std::move(ui)); -} - void MediaCaptureDevicesDispatcher::enqueueMediaAccessRequest(content::WebContents *webContents, const content::MediaStreamRequest &request ,const content::MediaResponseCallback &callback) { diff --git a/src/core/media_capture_devices_dispatcher.h b/src/core/media_capture_devices_dispatcher.h index c378c327e..579d159a4 100644 --- a/src/core/media_capture_devices_dispatcher.h +++ b/src/core/media_capture_devices_dispatcher.h @@ -116,8 +116,6 @@ class MediaCaptureDevicesDispatcher : public content::MediaObserver, // Helpers for ProcessMediaAccessRequest(). void processDesktopCaptureAccessRequest(content::WebContents *, const content::MediaStreamRequest &, const content::MediaResponseCallback &); - void processScreenCaptureAccessRequest(content::WebContents *,const content::MediaStreamRequest &, const content::MediaResponseCallback &); - void handleScreenCaptureAccessRequest(content::WebContents *, bool userAccepted, const base::string16 &/*unused callback_input*/); void enqueueMediaAccessRequest(content::WebContents *, const content::MediaStreamRequest &, const content::MediaResponseCallback &); void ProcessQueuedAccessRequest(content::WebContents *); diff --git a/src/core/native_web_keyboard_event_qt.cpp b/src/core/native_web_keyboard_event_qt.cpp index 86fa5c8b1..9eb613e25 100644 --- a/src/core/native_web_keyboard_event_qt.cpp +++ b/src/core/native_web_keyboard_event_qt.cpp @@ -66,9 +66,9 @@ using blink::WebKeyboardEvent; namespace content { -NativeWebKeyboardEvent::NativeWebKeyboardEvent() - : os_event(0), - skip_in_browser(false) +NativeWebKeyboardEvent::NativeWebKeyboardEvent(blink::WebInputEvent::Type, int, base::TimeTicks) + : os_event(0) + , skip_in_browser(false) { } diff --git a/src/core/network_delegate_qt.cpp b/src/core/network_delegate_qt.cpp index 9b4c415c9..90d4e6ce2 100644 --- a/src/core/network_delegate_qt.cpp +++ b/src/core/network_delegate_qt.cpp @@ -296,7 +296,7 @@ bool NetworkDelegateQt::OnCanGetCookies(const net::URLRequest&, const net::Cooki return true; } -bool NetworkDelegateQt::OnCanAccessFile(const net::URLRequest& request, const base::FilePath& path) const +bool NetworkDelegateQt::OnCanAccessFile(const net::URLRequest&, const base::FilePath&, const base::FilePath&) const { return true; } @@ -311,12 +311,27 @@ bool NetworkDelegateQt::OnAreExperimentalCookieFeaturesEnabled() const return false; } -bool NetworkDelegateQt::OnAreStrictSecureCookiesEnabled() const +bool NetworkDelegateQt::OnCancelURLRequestWithPolicyViolatingReferrerHeader(const net::URLRequest&, const GURL&, const GURL&) const { return false; } -bool NetworkDelegateQt::OnCancelURLRequestWithPolicyViolatingReferrerHeader(const net::URLRequest&, const GURL&, const GURL&) const +bool NetworkDelegateQt::OnCanQueueReportingReport(const url::Origin& origin) const +{ + return false; +} + +bool NetworkDelegateQt::OnCanSendReportingReport(const url::Origin& origin) const +{ + return false; +} + +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; } diff --git a/src/core/network_delegate_qt.h b/src/core/network_delegate_qt.h index 4ded56a9d..3607d8ab0 100644 --- a/src/core/network_delegate_qt.h +++ b/src/core/network_delegate_qt.h @@ -89,11 +89,18 @@ public: virtual void OnPACScriptError(int, const base::string16&) override; virtual net::NetworkDelegate::AuthRequiredResponse OnAuthRequired(net::URLRequest*, const net::AuthChallengeInfo&, const AuthCallback&, net::AuthCredentials*) override; virtual bool OnCanGetCookies(const net::URLRequest&, const net::CookieList&) override; - virtual bool OnCanAccessFile(const net::URLRequest& request, const base::FilePath& path) const override; + virtual bool OnCanAccessFile(const net::URLRequest&, const base::FilePath&, const base::FilePath&) const override; + virtual bool OnCanEnablePrivacyMode(const GURL&, const GURL&) const override; virtual bool OnAreExperimentalCookieFeaturesEnabled() const override; - virtual bool OnAreStrictSecureCookiesEnabled() const override; virtual bool OnCancelURLRequestWithPolicyViolatingReferrerHeader(const net::URLRequest&, const GURL&, const GURL&) const override; + + virtual bool OnCanQueueReportingReport(const url::Origin& origin) const override; + virtual bool OnCanSendReportingReport(const url::Origin& origin) const override; + virtual bool OnCanSetReportingClient(const url::Origin& origin, + const GURL& endpoint) const override; + virtual bool OnCanUseReportingClient(const url::Origin& origin, + const GURL& endpoint) const override; }; } // namespace QtWebEngineCore diff --git a/src/core/ozone_platform_qt.cpp b/src/core/ozone_platform_qt.cpp index 9cdafa279..e165239bd 100644 --- a/src/core/ozone_platform_qt.cpp +++ b/src/core/ozone_platform_qt.cpp @@ -99,6 +99,7 @@ public: // PlatformEventDispatcher: bool CanDispatchEvent(const PlatformEvent& event) override; uint32_t DispatchEvent(const PlatformEvent& event) override; + void PrepareForShutdown() override; private: PlatformWindowDelegate* delegate_; @@ -134,6 +135,11 @@ uint32_t PlatformWindowQt::DispatchEvent(const ui::PlatformEvent& native_event) return ui::POST_DISPATCH_STOP_PROPAGATION; } +void PlatformWindowQt::PrepareForShutdown() +{ +} + + class OzonePlatformQt : public OzonePlatform { public: OzonePlatformQt(); @@ -143,14 +149,14 @@ public: ui::CursorFactoryOzone* GetCursorFactoryOzone() override; GpuPlatformSupportHost* GetGpuPlatformSupportHost() override; std::unique_ptr<PlatformWindow> CreatePlatformWindow(PlatformWindowDelegate* delegate, const gfx::Rect& bounds) override; - std::unique_ptr<ui::NativeDisplayDelegate> CreateNativeDisplayDelegate() override; + std::unique_ptr<display::NativeDisplayDelegate> CreateNativeDisplayDelegate() override; ui::InputController* GetInputController() override; std::unique_ptr<ui::SystemInputInjector> CreateSystemInputInjector() override; ui::OverlayManagerOzone* GetOverlayManager() override; private: - void InitializeUI() override; - void InitializeGPU() override; + 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_; @@ -202,13 +208,13 @@ ui::OverlayManagerOzone* OzonePlatformQt::GetOverlayManager() return overlay_manager_.get(); } -std::unique_ptr<ui::NativeDisplayDelegate> OzonePlatformQt::CreateNativeDisplayDelegate() +std::unique_ptr<display::NativeDisplayDelegate> OzonePlatformQt::CreateNativeDisplayDelegate() { NOTREACHED(); return nullptr; } -void OzonePlatformQt::InitializeUI() +void OzonePlatformQt::InitializeUI(const ui::OzonePlatform::InitParams &) { overlay_manager_.reset(new StubOverlayManager()); cursor_factory_ozone_.reset(new CursorFactoryOzone()); @@ -216,7 +222,7 @@ void OzonePlatformQt::InitializeUI() input_controller_ = CreateStubInputController(); } -void OzonePlatformQt::InitializeGPU() +void OzonePlatformQt::InitializeGPU(const ui::OzonePlatform::InitParams &) { surface_factory_ozone_.reset(new QtWebEngineCore::SurfaceFactoryQt()); } @@ -226,7 +232,7 @@ void OzonePlatformQt::InitializeGPU() OzonePlatform* CreateOzonePlatformQt() { return new OzonePlatformQt; } -ClientNativePixmapFactory* CreateClientNativePixmapFactoryQt() +gfx::ClientNativePixmapFactory* CreateClientNativePixmapFactoryQt() { return CreateStubClientNativePixmapFactory(); } diff --git a/src/core/pdfium_document_wrapper_qt.cpp b/src/core/pdfium_document_wrapper_qt.cpp index ccf8e15fe..ca1e8cd07 100644 --- a/src/core/pdfium_document_wrapper_qt.cpp +++ b/src/core/pdfium_document_wrapper_qt.cpp @@ -36,7 +36,12 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#if defined (ENABLE_PDF) +#include "pdf/features.h" +#if BUILDFLAG(ENABLE_PDF) +#define ENABLE_PDF +#endif + +#if defined(ENABLE_PDF) #include "pdfium_document_wrapper_qt.h" #include <QtCore/qhash.h> diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp index 970a608a3..5328166d1 100644 --- a/src/core/permission_manager_qt.cpp +++ b/src/core/permission_manager_qt.cpp @@ -88,18 +88,52 @@ void PermissionManagerQt::permissionRequestReply(const QUrl &origin, BrowserCont QPair<QUrl, BrowserContextAdapter::PermissionType> key(origin, type); m_permissions[key] = reply; blink::mojom::PermissionStatus status = reply ? blink::mojom::PermissionStatus::GRANTED : blink::mojom::PermissionStatus::DENIED; - auto it = m_requests.begin(); - while (it != m_requests.end()) { - if (it->origin == origin && it->type == type) { - it->callback.Run(status); - it = m_requests.erase(it); - } else - ++it; + { + auto it = m_requests.begin(); + while (it != m_requests.end()) { + if (it->origin == origin && it->type == type) { + it->callback.Run(status); + it = m_requests.erase(it); + } else + ++it; + } } Q_FOREACH (const RequestOrSubscription &subscriber, m_subscribers) { if (subscriber.origin == origin && subscriber.type == type) subscriber.callback.Run(status); } + + auto it = m_multiRequests.begin(); + while (it != m_multiRequests.end()) { + if (it->origin == origin) { + bool answerable = true; + std::vector<blink::mojom::PermissionStatus> result; + result.reserve(it->types.size()); + for (content::PermissionType permission : it->types) { + const BrowserContextAdapter::PermissionType permissionType = toQt(permission); + if (permissionType == BrowserContextAdapter::UnsupportedPermission) { + result.push_back(blink::mojom::PermissionStatus::DENIED); + continue; + } + + QPair<QUrl, BrowserContextAdapter::PermissionType> key(origin, permissionType); + if (!m_permissions.contains(key)) { + answerable = false; + break; + } + if (m_permissions[key]) + result.push_back(blink::mojom::PermissionStatus::GRANTED); + else + result.push_back(blink::mojom::PermissionStatus::DENIED); + } + if (answerable) { + it->callback.Run(result); + it = m_multiRequests.erase(it); + continue; + } + } + ++it; + } } bool PermissionManagerQt::checkPermission(const QUrl &origin, BrowserContextAdapter::PermissionType type) @@ -144,32 +178,46 @@ int PermissionManagerQt::RequestPermissions(const std::vector<content::Permissio bool /*user_gesture*/, const base::Callback<void(const std::vector<blink::mojom::PermissionStatus>&)>& callback) { - NOTIMPLEMENTED() << "RequestPermissions has not been implemented in QtWebEngine"; - Q_UNUSED(frameHost); - - std::vector<blink::mojom::PermissionStatus> result(permissions.size()); + bool answerable = true; + std::vector<blink::mojom::PermissionStatus> result; + result.reserve(permissions.size()); for (content::PermissionType permission : permissions) { const BrowserContextAdapter::PermissionType permissionType = toQt(permission); if (permissionType == BrowserContextAdapter::UnsupportedPermission) result.push_back(blink::mojom::PermissionStatus::DENIED); else { - QPair<QUrl, BrowserContextAdapter::PermissionType> key(toQt(requesting_origin), permissionType); - // TODO: Request permission from UI - if (m_permissions.contains(key) && m_permissions[key]) - result.push_back(blink::mojom::PermissionStatus::GRANTED); - else - result.push_back(blink::mojom::PermissionStatus::DENIED); + answerable = false; + break; } } + if (answerable) { + callback.Run(result); + return kNoPendingOperation; + } - callback.Run(result); - return kNoPendingOperation; + int request_id = ++m_requestIdCount; + content::WebContents *webContents = frameHost->GetRenderViewHost()->GetDelegate()->GetAsWebContents(); + WebContentsDelegateQt* contentsDelegate = static_cast<WebContentsDelegateQt*>(webContents->GetDelegate()); + Q_ASSERT(contentsDelegate); + MultiRequest request = { + permissions, + toQt(requesting_origin), + callback + }; + m_multiRequests.insert(request_id, request); + for (content::PermissionType permission : permissions) { + const BrowserContextAdapter::PermissionType permissionType = toQt(permission); + if (permissionType == BrowserContextAdapter::GeolocationPermission) + contentsDelegate->requestGeolocationPermission(request.origin); + } + return request_id; } void PermissionManagerQt::CancelPermissionRequest(int request_id) { // Should we add API to cancel permissions in the UI level? m_requests.remove(request_id); + m_multiRequests.remove(request_id); } blink::mojom::PermissionStatus PermissionManagerQt::GetPermissionStatus( @@ -202,14 +250,6 @@ void PermissionManagerQt::ResetPermission( m_permissions.remove(key); } -void PermissionManagerQt::RegisterPermissionUsage( - content::PermissionType /*permission*/, - const GURL& /*requesting_origin*/, - const GURL& /*embedding_origin*/) -{ - // We do not currently track which permissions are used. -} - int PermissionManagerQt::SubscribePermissionStatusChange( content::PermissionType permission, const GURL& requesting_origin, diff --git a/src/core/permission_manager_qt.h b/src/core/permission_manager_qt.h index 1cbb41b5e..f51ea3c59 100644 --- a/src/core/permission_manager_qt.h +++ b/src/core/permission_manager_qt.h @@ -87,11 +87,6 @@ public: const base::Callback<void( const std::vector<blink::mojom::PermissionStatus>&)>& callback) override; - void RegisterPermissionUsage( - content::PermissionType permission, - const GURL& requesting_origin, - const GURL& embedding_origin) override; - int SubscribePermissionStatusChange( content::PermissionType permission, const GURL& requesting_origin, @@ -107,8 +102,14 @@ private: QUrl origin; base::Callback<void(blink::mojom::PermissionStatus)> callback; }; + struct MultiRequest { + std::vector<content::PermissionType> types; + QUrl origin; + base::Callback<void(const std::vector<blink::mojom::PermissionStatus>&)> callback; + }; QHash<int, RequestOrSubscription> m_requests; QHash<int, RequestOrSubscription> m_subscribers; + QHash<int, MultiRequest> m_multiRequests; int m_requestIdCount; int m_subscriberIdCount; diff --git a/src/core/print_view_manager_base_qt.cpp b/src/core/print_view_manager_base_qt.cpp index a5d832529..cbd8ea03a 100644 --- a/src/core/print_view_manager_base_qt.cpp +++ b/src/core/print_view_manager_base_qt.cpp @@ -72,7 +72,9 @@ PrintViewManagerBaseQt::PrintViewManagerBaseQt(content::WebContents *contents) : printing::PrintManager(contents) , cookie_(0) , m_isInsideInnerMessageLoop(false) +#if !defined(OS_MACOSX) , m_isExpectingFirstPage(false) +#endif , m_didPrintingSucceed(false) , m_printerQueriesQueue(WebEngineContext::current()->getPrintJobManager()->queue()) { diff --git a/src/core/print_view_manager_base_qt.h b/src/core/print_view_manager_base_qt.h index 511a104bf..4e4c8bde2 100644 --- a/src/core/print_view_manager_base_qt.h +++ b/src/core/print_view_manager_base_qt.h @@ -149,7 +149,9 @@ private: base::Closure m_quitClosure; bool m_isInsideInnerMessageLoop; +#if !defined(OS_MACOSX) bool m_isExpectingFirstPage; +#endif bool m_didPrintingSucceed; scoped_refptr<printing::PrintQueriesQueue> m_printerQueriesQueue; // content::WebContentsObserver implementation. diff --git a/src/core/print_view_manager_qt.cpp b/src/core/print_view_manager_qt.cpp index f2d78365d..7c482b012 100644 --- a/src/core/print_view_manager_qt.cpp +++ b/src/core/print_view_manager_qt.cpp @@ -60,6 +60,7 @@ #include "content/public/common/web_preferences.h" #include "printing/pdf_metafile_skia.h" #include "printing/print_job_constants.h" +#include "printing/units.h" DEFINE_WEB_CONTENTS_USER_DATA_KEY(QtWebEngineCore::PrintViewManagerQt); @@ -132,6 +133,10 @@ static base::DictionaryValue *createPrintSettings() printSettings->SetBoolean(printing::kSettingGenerateDraftData, false); printSettings->SetBoolean(printing::kSettingPreviewModifiable, false); + + printSettings->SetInteger(printing::kSettingDpiHorizontal, printing::kPointsPerInch); + printSettings->SetInteger(printing::kSettingDpiVertical, printing::kPointsPerInch); + printSettings->SetInteger(printing::kSettingDuplexMode, printing::SIMPLEX); printSettings->SetInteger(printing::kSettingCopies, 1); printSettings->SetBoolean(printing::kSettingCollate, false); @@ -141,6 +146,7 @@ static base::DictionaryValue *createPrintSettings() printSettings->SetBoolean(printing::kSettingShouldPrintSelectionOnly, false); printSettings->SetBoolean(printing::kSettingShouldPrintBackgrounds, true); printSettings->SetBoolean(printing::kSettingHeaderFooterEnabled, false); + printSettings->SetBoolean(printing::kSettingRasterizePdf, false); printSettings->SetInteger(printing::kSettingScaleFactor, 100); printSettings->SetString(printing::kSettingDeviceName, ""); printSettings->SetInteger(printing::kPreviewUIID, 12345678); @@ -148,27 +154,37 @@ static base::DictionaryValue *createPrintSettings() return printSettings; } -static base::DictionaryValue *createPrintSettingsFromQPageLayout(const QPageLayout &pageLayout) +static base::DictionaryValue *createPrintSettingsFromQPageLayout(const QPageLayout &pageLayout, bool printToPdf) { base::DictionaryValue *printSettings = createPrintSettings(); //Set page size attributes, chromium expects these in micrometers - QSizeF pageSizeInMilimeter = pageLayout.pageSize().size(QPageSize::Millimeter); + QRectF pageSizeInMillimeter = pageLayout.pageSize().rect(QPageSize::Millimeter); + if (!printToPdf) { + // QPrinter will extend this size with its margins + QMarginsF margins = pageLayout.margins(QPageLayout::Millimeter); + pageSizeInMillimeter = pageSizeInMillimeter.marginsRemoved(margins); + } std::unique_ptr<base::DictionaryValue> sizeDict(new base::DictionaryValue); - sizeDict->SetInteger(printing::kSettingMediaSizeWidthMicrons, pageSizeInMilimeter.width() * kMicronsToMillimeter); - sizeDict->SetInteger(printing::kSettingMediaSizeHeightMicrons, pageSizeInMilimeter.height() * kMicronsToMillimeter); + sizeDict->SetInteger(printing::kSettingMediaSizeWidthMicrons, pageSizeInMillimeter.width() * kMicronsToMillimeter); + sizeDict->SetInteger(printing::kSettingMediaSizeHeightMicrons, pageSizeInMillimeter.height() * kMicronsToMillimeter); printSettings->Set(printing::kSettingMediaSize, std::move(sizeDict)); - // Apply page margins - QMargins pageMarginsInPoints = pageLayout.marginsPoints(); - std::unique_ptr<base::DictionaryValue> marginsDict(new base::DictionaryValue); - marginsDict->SetInteger(printing::kSettingMarginTop, pageMarginsInPoints.top()); - marginsDict->SetInteger(printing::kSettingMarginBottom, pageMarginsInPoints.bottom()); - marginsDict->SetInteger(printing::kSettingMarginLeft, pageMarginsInPoints.left()); - marginsDict->SetInteger(printing::kSettingMarginRight, pageMarginsInPoints.right()); - - printSettings->Set(printing::kSettingMarginsCustom, std::move(marginsDict)); - printSettings->SetInteger(printing::kSettingMarginsType, printing::CUSTOM_MARGINS); + if (printToPdf) { + // Apply page margins when printing to PDF + QMargins pageMarginsInPoints = pageLayout.marginsPoints(); + std::unique_ptr<base::DictionaryValue> marginsDict(new base::DictionaryValue); + marginsDict->SetInteger(printing::kSettingMarginTop, pageMarginsInPoints.top()); + marginsDict->SetInteger(printing::kSettingMarginBottom, pageMarginsInPoints.bottom()); + marginsDict->SetInteger(printing::kSettingMarginLeft, pageMarginsInPoints.left()); + marginsDict->SetInteger(printing::kSettingMarginRight, pageMarginsInPoints.right()); + + printSettings->Set(printing::kSettingMarginsCustom, std::move(marginsDict)); + printSettings->SetInteger(printing::kSettingMarginsType, printing::CUSTOM_MARGINS); + } else { + // QPrinter will handle margins + printSettings->SetInteger(printing::kSettingMarginsType, printing::NO_MARGINS); + } printSettings->SetBoolean(printing::kSettingLandscape, pageLayout.orientation() == QPageLayout::Landscape); @@ -238,7 +254,7 @@ bool PrintViewManagerQt::PrintToPDFInternal(const QPageLayout &pageLayout, bool if (!pageLayout.isValid()) return false; - m_printSettings.reset(createPrintSettingsFromQPageLayout(pageLayout)); + m_printSettings.reset(createPrintSettingsFromQPageLayout(pageLayout, !m_pdfOutputPath.empty())); m_printSettings->SetBoolean(printing::kSettingShouldPrintBackgrounds , web_contents()->GetRenderViewHost()->GetWebkitPreferences().should_print_backgrounds); m_printSettings->SetInteger(printing::kSettingColor, diff --git a/src/core/qtwebengine.gni b/src/core/qtwebengine.gni index bb269baa2..c9f766a36 100644 --- a/src/core/qtwebengine.gni +++ b/src/core/qtwebengine.gni @@ -1,3 +1,4 @@ +import("//media/media_options.gni") import("//third_party/widevine/cdm/widevine.gni") chromium_version = exec_script("//build/util/version.py", [ "-f", rebase_path("//chrome/VERSION"), @@ -11,6 +12,7 @@ include_dirs = [ deps = [ "//base", + "//chrome/common:features", "//components/error_page/common", "//components/keyed_service/content", "//components/visitedlink/browser", @@ -22,10 +24,11 @@ deps = [ "//content/public/browser", "//content/public/common", "//content/public/renderer", + "//media:media_features", "//net:net_browser_services", + "//net:net_with_v8", "//skia", "//third_party/WebKit/public:blink", - "//third_party/webrtc/base:base", "//ui/accessibility", "//third_party/mesa:mesa_headers", ":qtwebengine_sources", @@ -36,6 +39,10 @@ if (enable_widevine) { deps += [ "//components/cdm/renderer"] } +if (enable_webrtc) { + deps += [ "//third_party/webrtc/base:base" ] +} + if (is_linux && !is_desktop_linux) { deps += [ "//ui/events/ozone:events_ozone_evdev"] } diff --git a/src/core/qtwebengine_resources.gni b/src/core/qtwebengine_resources.gni index a7ffb40f3..acf5f1590 100644 --- a/src/core/qtwebengine_resources.gni +++ b/src/core/qtwebengine_resources.gni @@ -70,7 +70,7 @@ repack("qtwebengine_repack_resources_200") { repack("qtwebengine_repack_resources_devtools") { sources = [ - "$root_gen_dir/blink/devtools_resources.pak", + "$root_gen_dir/content/browser/devtools/devtools_resources.pak", ] output = "$root_out_dir/qtwebengine_devtools_resources.pak" deps = [ diff --git a/src/core/qtwebengine_sources.gni b/src/core/qtwebengine_sources.gni index 9a559732d..9a2d4aee5 100644 --- a/src/core/qtwebengine_sources.gni +++ b/src/core/qtwebengine_sources.gni @@ -1,29 +1,32 @@ import("//build/config/features.gni") +import("//build/config/ui.gni") import("//components/spellcheck/spellcheck_build_features.gni") +import("//pdf/features.gni") +import("//ppapi/features/features.gni") import("//printing/features/features.gni") source_set("qtwebengine_spellcheck_sources") { sources = [ + "//chrome/browser/spellchecker/spell_check_host_impl.cc", + "//chrome/browser/spellchecker/spell_check_host_impl.h", "//chrome/browser/spellchecker/spellcheck_custom_dictionary.cc", "//chrome/browser/spellchecker/spellcheck_custom_dictionary.h", "//chrome/browser/spellchecker/spellcheck_factory.cc", "//chrome/browser/spellchecker/spellcheck_factory.h", "//chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc", "//chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h", - "//chrome/browser/spellchecker/spellcheck_message_filter.cc", - "//chrome/browser/spellchecker/spellcheck_message_filter.h", "//chrome/browser/spellchecker/spellcheck_service.cc", "//chrome/browser/spellchecker/spellcheck_service.h", ] deps = [ "//components/spellcheck/browser", "//components/spellcheck/renderer", + "//third_party/boringssl", "//third_party/WebKit/public:blink", "//third_party/hunspell", ] if (is_mac && use_browser_spellchecker) { sources += [ - "//chrome/browser/spellchecker/spellcheck_message_filter_platform.h", "//chrome/browser/spellchecker/spellcheck_message_filter_platform_mac.cc", ] } @@ -43,8 +46,8 @@ source_set("qtwebengine_sources") { "//chrome/browser/media/webrtc/desktop_streams_registry.h", "//chrome/common/chrome_switches.cc", "//chrome/common/chrome_switches.h", - "//components/prefs/testing_pref_store.cc", - "//components/prefs/testing_pref_store.h", + "//components/prefs/in_memory_pref_store.cc", + "//components/prefs/in_memory_pref_store.h", "//extensions/common/constants.cc", "//extensions/common/constants.h", "//extensions/common/url_pattern.cc", @@ -99,10 +102,10 @@ source_set("qtwebengine_sources") { if (enable_pdf) { deps += [ "//pdf", + "//pdf:features", "//components/printing/browser", "//components/printing/renderer", ] } - } diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index ef2834041..cae2094fd 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -53,7 +53,10 @@ #include "base/command_line.h" #include "cc/output/direct_renderer.h" +#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h" #include "content/browser/accessibility/browser_accessibility_state_impl.h" +#include "content/browser/browser_main_loop.h" +#include "content/browser/frame_host/render_frame_host_impl.h" #include "content/browser/frame_host/frame_tree.h" #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/common/cursors/webcursor.h" @@ -70,12 +73,17 @@ #include "ui/events/event.h" #include "ui/events/gesture_detection/gesture_provider_config_helper.h" #include "ui/events/gesture_detection/motion_event.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/geometry/size_conversions.h" #if defined(USE_AURA) +#include "ui/base/cursor/cursor.h" #include "ui/base/cursor/cursors_aura.h" #endif +#include <private/qguiapplication_p.h> +#include <qpa/qplatforminputcontext.h> +#include <qpa/qplatformintegration.h> #include <QEvent> #include <QFocusEvent> #include <QGuiApplication> @@ -90,6 +98,9 @@ #include <QVariant> #include <QWheelEvent> #include <QWindow> +#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) +#include <QtGui/private/qinputcontrol_p.h> +#endif #include <QtGui/qaccessible.h> namespace QtWebEngineCore { @@ -105,9 +116,9 @@ enum ImStateFlags { static inline ui::LatencyInfo CreateLatencyInfo(const blink::WebInputEvent& event) { ui::LatencyInfo latency_info; // The latency number should only be added if the timestamp is valid. - if (event.timeStampSeconds) { + if (event.TimeStampSeconds()) { const int64_t time_micros = static_cast<int64_t>( - event.timeStampSeconds * base::Time::kMicrosecondsPerSecond); + event.TimeStampSeconds() * base::Time::kMicrosecondsPerSecond); latency_info.AddLatencyNumberWithTimestamp( ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, @@ -177,6 +188,59 @@ static inline bool compareTouchPoints(const QTouchEvent::TouchPoint &lhs, const return lhs.state() < rhs.state(); } +static inline bool isCommonTextEditShortcut(const QKeyEvent *ke) +{ +#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) + return QInputControl::isCommonTextEditShortcut(ke); +#else + if (ke->modifiers() == Qt::NoModifier + || ke->modifiers() == Qt::ShiftModifier + || ke->modifiers() == Qt::KeypadModifier) { + if (ke->key() < Qt::Key_Escape) { + return true; + } else { + switch (ke->key()) { + case Qt::Key_Return: + case Qt::Key_Enter: + case Qt::Key_Delete: + case Qt::Key_Home: + case Qt::Key_End: + case Qt::Key_Backspace: + case Qt::Key_Left: + case Qt::Key_Right: + case Qt::Key_Up: + case Qt::Key_Down: + case Qt::Key_Tab: + return true; + default: + break; + } + } + } else if (ke->matches(QKeySequence::Copy) + || ke->matches(QKeySequence::Paste) + || ke->matches(QKeySequence::Cut) + || ke->matches(QKeySequence::Redo) + || ke->matches(QKeySequence::Undo) + || ke->matches(QKeySequence::MoveToNextWord) + || ke->matches(QKeySequence::MoveToPreviousWord) + || ke->matches(QKeySequence::MoveToStartOfDocument) + || ke->matches(QKeySequence::MoveToEndOfDocument) + || ke->matches(QKeySequence::SelectNextWord) + || ke->matches(QKeySequence::SelectPreviousWord) + || ke->matches(QKeySequence::SelectStartOfLine) + || ke->matches(QKeySequence::SelectEndOfLine) + || ke->matches(QKeySequence::SelectStartOfBlock) + || ke->matches(QKeySequence::SelectEndOfBlock) + || ke->matches(QKeySequence::SelectStartOfDocument) + || ke->matches(QKeySequence::SelectEndOfDocument) + || ke->matches(QKeySequence::SelectAll) + ) { + return true; + } + return false; +#endif +} + static uint32_t s_eventId = 0; class MotionEventQt : public ui::MotionEvent { public: @@ -218,7 +282,8 @@ public: } int GetFlags() const override { return flags; } float GetPressure(size_t pointer_index) const override { return touchPoints.at(pointer_index).pressure(); } - float GetTilt(size_t pointer_index) const override { return 0; } + float GetTiltX(size_t pointer_index) const override { return 0; } + float GetTiltY(size_t pointer_index) const override { return 0; } base::TimeTicks GetEventTime() const override { return eventTime; } size_t GetHistorySize() const override { return 0; } @@ -261,17 +326,20 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost* widget , m_needsDelegatedFrameAck(false) , m_loadVisuallyCommittedState(NotCommitted) , m_adapterClient(0) + , m_rendererCompositorFrameSink(0) , m_imeInProgress(false) , m_receivedEmptyImeText(false) , m_initPending(false) , m_beginFrameSource(nullptr) , m_needsBeginFrames(false) , m_addedFrameObserver(false) + , m_backgroundColor(SK_ColorWHITE) , m_imState(0) , m_anchorPositionWithinSelection(-1) , m_cursorPositionWithinSelection(-1) , m_cursorPosition(0) , m_emptyPreviousSelection(true) + , m_wheelAckPending(false) { auto* task_runner = base::ThreadTaskRunnerHandle::Get().get(); m_beginFrameSource.reset(new cc::DelayBasedBeginFrameSource( @@ -287,6 +355,9 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost* widget #endif // QT_NO_ACCESSIBILITY if (GetTextInputManager()) GetTextInputManager()->AddObserver(this); + + const QPlatformInputContext *context = QGuiApplicationPrivate::platformIntegration()->inputContext(); + m_imeHasHiddenTextCapability = context && context->hasCapability(QPlatformInputContext::HiddenTextCapability); } RenderWidgetHostViewQt::~RenderWidgetHostViewQt() @@ -444,12 +515,20 @@ gfx::Rect RenderWidgetHostViewQt::GetViewBounds() const return gfx::BoundingRect(p1, p2); } +SkColor RenderWidgetHostViewQt::background_color() const +{ + return m_backgroundColor; +} + void RenderWidgetHostViewQt::SetBackgroundColor(SkColor color) { - RenderWidgetHostViewBase::SetBackgroundColor(color); + if (m_backgroundColor == color) + return; + m_backgroundColor = color; // Set the background of the compositor if necessary m_delegate->setClearColor(toQt(color)); // Set the background of the blink::FrameView + m_host->SetBackgroundOpaque(SkColorGetA(color) == SK_AlphaOPAQUE); m_host->Send(new RenderViewObserverQt_SetBackgroundColor(m_host->GetRoutingID(), color)); } @@ -473,119 +552,119 @@ void RenderWidgetHostViewQt::UnlockMouse() void RenderWidgetHostViewQt::UpdateCursor(const content::WebCursor &webCursor) { - content::WebCursor::CursorInfo cursorInfo; + content::CursorInfo cursorInfo; webCursor.GetCursorInfo(&cursorInfo); Qt::CursorShape shape = Qt::ArrowCursor; #if defined(USE_AURA) - int auraType = -1; + ui::CursorType auraType = ui::CursorType::kNull; #endif switch (cursorInfo.type) { - case blink::WebCursorInfo::TypePointer: + case blink::WebCursorInfo::kTypePointer: shape = Qt::ArrowCursor; break; - case blink::WebCursorInfo::TypeCross: + case blink::WebCursorInfo::kTypeCross: shape = Qt::CrossCursor; break; - case blink::WebCursorInfo::TypeHand: + case blink::WebCursorInfo::kTypeHand: shape = Qt::PointingHandCursor; break; - case blink::WebCursorInfo::TypeIBeam: + case blink::WebCursorInfo::kTypeIBeam: shape = Qt::IBeamCursor; break; - case blink::WebCursorInfo::TypeWait: + case blink::WebCursorInfo::kTypeWait: shape = Qt::WaitCursor; break; - case blink::WebCursorInfo::TypeHelp: + case blink::WebCursorInfo::kTypeHelp: shape = Qt::WhatsThisCursor; break; - case blink::WebCursorInfo::TypeEastResize: - case blink::WebCursorInfo::TypeWestResize: - case blink::WebCursorInfo::TypeEastWestResize: - case blink::WebCursorInfo::TypeEastPanning: - case blink::WebCursorInfo::TypeWestPanning: + case blink::WebCursorInfo::kTypeEastResize: + case blink::WebCursorInfo::kTypeWestResize: + case blink::WebCursorInfo::kTypeEastWestResize: + case blink::WebCursorInfo::kTypeEastPanning: + case blink::WebCursorInfo::kTypeWestPanning: shape = Qt::SizeHorCursor; break; - case blink::WebCursorInfo::TypeNorthResize: - case blink::WebCursorInfo::TypeSouthResize: - case blink::WebCursorInfo::TypeNorthSouthResize: - case blink::WebCursorInfo::TypeNorthPanning: - case blink::WebCursorInfo::TypeSouthPanning: + case blink::WebCursorInfo::kTypeNorthResize: + case blink::WebCursorInfo::kTypeSouthResize: + case blink::WebCursorInfo::kTypeNorthSouthResize: + case blink::WebCursorInfo::kTypeNorthPanning: + case blink::WebCursorInfo::kTypeSouthPanning: shape = Qt::SizeVerCursor; break; - case blink::WebCursorInfo::TypeNorthEastResize: - case blink::WebCursorInfo::TypeSouthWestResize: - case blink::WebCursorInfo::TypeNorthEastSouthWestResize: - case blink::WebCursorInfo::TypeNorthEastPanning: - case blink::WebCursorInfo::TypeSouthWestPanning: + case blink::WebCursorInfo::kTypeNorthEastResize: + case blink::WebCursorInfo::kTypeSouthWestResize: + case blink::WebCursorInfo::kTypeNorthEastSouthWestResize: + case blink::WebCursorInfo::kTypeNorthEastPanning: + case blink::WebCursorInfo::kTypeSouthWestPanning: shape = Qt::SizeBDiagCursor; break; - case blink::WebCursorInfo::TypeNorthWestResize: - case blink::WebCursorInfo::TypeSouthEastResize: - case blink::WebCursorInfo::TypeNorthWestSouthEastResize: - case blink::WebCursorInfo::TypeNorthWestPanning: - case blink::WebCursorInfo::TypeSouthEastPanning: + case blink::WebCursorInfo::kTypeNorthWestResize: + case blink::WebCursorInfo::kTypeSouthEastResize: + case blink::WebCursorInfo::kTypeNorthWestSouthEastResize: + case blink::WebCursorInfo::kTypeNorthWestPanning: + case blink::WebCursorInfo::kTypeSouthEastPanning: shape = Qt::SizeFDiagCursor; break; - case blink::WebCursorInfo::TypeColumnResize: + case blink::WebCursorInfo::kTypeColumnResize: shape = Qt::SplitHCursor; break; - case blink::WebCursorInfo::TypeRowResize: + case blink::WebCursorInfo::kTypeRowResize: shape = Qt::SplitVCursor; break; - case blink::WebCursorInfo::TypeMiddlePanning: - case blink::WebCursorInfo::TypeMove: + case blink::WebCursorInfo::kTypeMiddlePanning: + case blink::WebCursorInfo::kTypeMove: shape = Qt::SizeAllCursor; break; - case blink::WebCursorInfo::TypeProgress: + case blink::WebCursorInfo::kTypeProgress: shape = Qt::BusyCursor; break; #if defined(USE_AURA) - case blink::WebCursorInfo::TypeVerticalText: - auraType = ui::kCursorVerticalText; + case blink::WebCursorInfo::kTypeVerticalText: + auraType = ui::CursorType::kVerticalText; break; - case blink::WebCursorInfo::TypeCell: - auraType = ui::kCursorCell; + case blink::WebCursorInfo::kTypeCell: + auraType = ui::CursorType::kCell; break; - case blink::WebCursorInfo::TypeContextMenu: - auraType = ui::kCursorContextMenu; + case blink::WebCursorInfo::kTypeContextMenu: + auraType = ui::CursorType::kContextMenu; break; - case blink::WebCursorInfo::TypeAlias: - auraType = ui::kCursorAlias; + case blink::WebCursorInfo::kTypeAlias: + auraType = ui::CursorType::kAlias; break; - case blink::WebCursorInfo::TypeCopy: - auraType = ui::kCursorCopy; + case blink::WebCursorInfo::kTypeCopy: + auraType = ui::CursorType::kCopy; break; - case blink::WebCursorInfo::TypeZoomIn: - auraType = ui::kCursorZoomIn; + case blink::WebCursorInfo::kTypeZoomIn: + auraType = ui::CursorType::kZoomIn; break; - case blink::WebCursorInfo::TypeZoomOut: - auraType = ui::kCursorZoomOut; + case blink::WebCursorInfo::kTypeZoomOut: + auraType = ui::CursorType::kZoomOut; break; #else - case blink::WebCursorInfo::TypeVerticalText: - case blink::WebCursorInfo::TypeCell: - case blink::WebCursorInfo::TypeContextMenu: - case blink::WebCursorInfo::TypeAlias: - case blink::WebCursorInfo::TypeCopy: - case blink::WebCursorInfo::TypeZoomIn: - case blink::WebCursorInfo::TypeZoomOut: + case blink::WebCursorInfo::kTypeVerticalText: + case blink::WebCursorInfo::kTypeCell: + case blink::WebCursorInfo::kTypeContextMenu: + case blink::WebCursorInfo::kTypeAlias: + case blink::WebCursorInfo::kTypeCopy: + case blink::WebCursorInfo::kTypeZoomIn: + case blink::WebCursorInfo::kTypeZoomOut: // FIXME: Support on OS X break; #endif - case blink::WebCursorInfo::TypeNoDrop: - case blink::WebCursorInfo::TypeNotAllowed: + case blink::WebCursorInfo::kTypeNoDrop: + case blink::WebCursorInfo::kTypeNotAllowed: shape = Qt::ForbiddenCursor; break; - case blink::WebCursorInfo::TypeNone: + case blink::WebCursorInfo::kTypeNone: shape = Qt::BlankCursor; break; - case blink::WebCursorInfo::TypeGrab: + case blink::WebCursorInfo::kTypeGrab: shape = Qt::OpenHandCursor; break; - case blink::WebCursorInfo::TypeGrabbing: + case blink::WebCursorInfo::kTypeGrabbing: shape = Qt::ClosedHandCursor; break; - case blink::WebCursorInfo::TypeCustom: + case blink::WebCursorInfo::kTypeCustom: 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())); @@ -594,7 +673,7 @@ void RenderWidgetHostViewQt::UpdateCursor(const content::WebCursor &webCursor) break; } #if defined(USE_AURA) - if (auraType > 0) { + if (auraType != ui::CursorType::kNull) { SkBitmap bitmap; gfx::Point hotspot; if (ui::GetCursorBitmap(auraType, &bitmap, &hotspot)) { @@ -640,54 +719,36 @@ void RenderWidgetHostViewQt::SetTooltipText(const base::string16 &tooltip_text) m_adapterClient->setToolTip(toQt(tooltip_text)); } -void RenderWidgetHostViewQt::CopyFromCompositingSurface(const gfx::Rect& src_subrect, const gfx::Size& dst_size, const content::ReadbackRequestCallback& callback, const SkColorType color_type) -{ - NOTIMPLEMENTED(); - Q_UNUSED(src_subrect); - Q_UNUSED(dst_size); - Q_UNUSED(color_type); - callback.Run(SkBitmap(), content::READBACK_FAILED); -} - -void RenderWidgetHostViewQt::CopyFromCompositingSurfaceToVideoFrame(const gfx::Rect& src_subrect, const scoped_refptr<media::VideoFrame>& target, const base::Callback<void(const gfx::Rect&, bool)>& callback) -{ - NOTIMPLEMENTED(); - callback.Run(gfx::Rect(), false); -} - -bool RenderWidgetHostViewQt::CanCopyToVideoFrame() const -{ - return false; -} - bool RenderWidgetHostViewQt::HasAcceleratedSurface(const gfx::Size&) { return false; } -void RenderWidgetHostViewQt::LockCompositingSurface() +void RenderWidgetHostViewQt::DidCreateNewRendererCompositorFrameSink(cc::mojom::CompositorFrameSinkClient *frameSink) { + // Accumulated resources belong to the old RendererCompositorFrameSink and + // should not be returned. + m_resourcesToRelease.clear(); + m_rendererCompositorFrameSink = frameSink; } -void RenderWidgetHostViewQt::UnlockCompositingSurface() -{ -} - -void RenderWidgetHostViewQt::OnSwapCompositorFrame(uint32_t output_surface_id, cc::CompositorFrame frame) +void RenderWidgetHostViewQt::SubmitCompositorFrame(const viz::LocalSurfaceId &local_surface_id, cc::CompositorFrame frame) { bool scrollOffsetChanged = (m_lastScrollOffset != frame.metadata.root_scroll_offset); bool contentsSizeChanged = (m_lastContentsSize != frame.metadata.root_layer_size); m_lastScrollOffset = frame.metadata.root_scroll_offset; m_lastContentsSize = frame.metadata.root_layer_size; + m_backgroundColor = frame.metadata.root_background_color; + if (m_localSurfaceId != local_surface_id) { + m_localSurfaceId = local_surface_id; + // FIXME: update frame_size and device_scale_factor? + // FIXME: showPrimarySurface()? + } Q_ASSERT(!m_needsDelegatedFrameAck); m_needsDelegatedFrameAck = true; - m_pendingOutputSurfaceId = output_surface_id; - Q_ASSERT(frame.delegated_frame_data); - Q_ASSERT(!m_chromiumCompositorData->frameData || m_chromiumCompositorData->frameData->resource_list.empty()); - if (m_chromiumCompositorData->frameData.get()) - m_chromiumCompositorData->previousFrameData = std::move(m_chromiumCompositorData->frameData); - m_chromiumCompositorData->frameData = std::move(frame.delegated_frame_data); + m_chromiumCompositorData->previousFrameData = std::move(m_chromiumCompositorData->frameData); m_chromiumCompositorData->frameDevicePixelRatio = frame.metadata.device_scale_factor; + m_chromiumCompositorData->frameData = std::move(frame); // Support experimental.viewport.devicePixelRatio, see GetScreenInfo implementation below. float dpiScale = this->dpiScale(); @@ -740,7 +801,7 @@ void RenderWidgetHostViewQt::OnUpdateTextInputStateCalled(content::TextInputMana Q_UNUSED(did_update_state); ui::TextInputType type = getTextInputType(); - m_delegate->inputMethodStateChanged(type != ui::TEXT_INPUT_TYPE_NONE); + m_delegate->inputMethodStateChanged(type != ui::TEXT_INPUT_TYPE_NONE, type == ui::TEXT_INPUT_TYPE_PASSWORD); m_delegate->setInputMethodHints(toQtInputMethodHints(type)); const content::TextInputState *state = text_input_manager_->GetTextInputState(); @@ -789,11 +850,15 @@ void RenderWidgetHostViewQt::OnTextSelectionChanged(content::TextInputManager *t Q_UNUSED(text_input_manager); Q_UNUSED(updated_view); + const content::TextInputManager::TextSelection *selection = GetTextInputManager()->GetTextSelection(updated_view); + if (!selection) + return; + #if defined(USE_X11) - if (!GetSelectedText().empty()) { + if (!selection->selected_text().empty() && selection->user_initiated()) { // Set the CLIPBOARD_TYPE_SELECTION to the ui::Clipboard. ui::ScopedClipboardWriter clipboard_writer(ui::CLIPBOARD_TYPE_SELECTION); - clipboard_writer.WriteText(GetSelectedText()); + clipboard_writer.WriteText(selection->selected_text()); } #endif // defined(USE_X11) @@ -825,29 +890,34 @@ void RenderWidgetHostViewQt::selectionChanged() return; } - const content::TextInputManager::TextSelection *selection = text_input_manager_->GetTextSelection(); - if (!selection) + if (GetSelectedText().empty()) { + m_anchorPositionWithinSelection = m_cursorPosition; + m_cursorPositionWithinSelection = m_cursorPosition; + + if (!m_emptyPreviousSelection) { + m_emptyPreviousSelection = GetSelectedText().empty(); + m_adapterClient->selectionChanged(); + } + return; + } - if (!selection->range.IsValid()) + const content::TextInputManager::TextSelection *selection = text_input_manager_->GetTextSelection(); + if (!selection) return; - // Avoid duplicate empty selectionChanged() signals - if (GetSelectedText().empty() && m_emptyPreviousSelection) { - m_anchorPositionWithinSelection = m_cursorPosition; - m_cursorPositionWithinSelection = m_cursorPosition; + if (!selection->range().IsValid()) return; - } int newAnchorPositionWithinSelection = 0; int newCursorPositionWithinSelection = 0; if (text_input_manager_->GetSelectionRegion()->anchor.type() == gfx::SelectionBound::RIGHT) { - newAnchorPositionWithinSelection = selection->range.GetMax() - selection->offset; - newCursorPositionWithinSelection = selection->range.GetMin() - selection->offset; + newAnchorPositionWithinSelection = selection->range().GetMax() - selection->offset(); + newCursorPositionWithinSelection = selection->range().GetMin() - selection->offset(); } else { - newAnchorPositionWithinSelection = selection->range.GetMin() - selection->offset; - newCursorPositionWithinSelection = selection->range.GetMax() - selection->offset; + newAnchorPositionWithinSelection = selection->range().GetMin() - selection->offset(); + newCursorPositionWithinSelection = selection->range().GetMax() - selection->offset(); } if (m_anchorPositionWithinSelection == newAnchorPositionWithinSelection && m_cursorPositionWithinSelection == newCursorPositionWithinSelection) @@ -856,10 +926,10 @@ void RenderWidgetHostViewQt::selectionChanged() m_anchorPositionWithinSelection = newAnchorPositionWithinSelection; m_cursorPositionWithinSelection = newCursorPositionWithinSelection; - if (!GetSelectedText().empty()) + if (!selection->selected_text().empty()) m_cursorPosition = newCursorPositionWithinSelection; - m_emptyPreviousSelection = GetSelectedText().empty(); + m_emptyPreviousSelection = selection->selected_text().empty(); m_adapterClient->selectionChanged(); } @@ -917,7 +987,44 @@ void RenderWidgetHostViewQt::windowChanged() bool RenderWidgetHostViewQt::forwardEvent(QEvent *event) { + Q_ASSERT(m_host->GetView()); + switch (event->type()) { + case QEvent::ShortcutOverride: { + QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event); + + auto acceptKeyOutOfInputField = [](QKeyEvent *keyEvent) -> bool { +#ifdef Q_OS_MACOS + // Try triggering a registered shortcut + if (QGuiApplicationPrivate::instance()->shortcutMap.tryShortcut(keyEvent)) + return false; + + // The following shortcuts are handled out of input field too but + // disabled on macOS to let the blinking menu handling to the + // embedder application (see kKeyboardCodeKeyDownEntries in + // third_party/WebKit/Source/core/editing/EditingBehavior.cpp). + // Let them pass on macOS to generate the corresponding edit command. + return keyEvent->matches(QKeySequence::Copy) + || keyEvent->matches(QKeySequence::Paste) + || keyEvent->matches(QKeySequence::Cut) + || keyEvent->matches(QKeySequence::SelectAll); +#else + return false; +#endif + }; + + if (!inputMethodQuery(Qt::ImEnabled).toBool() && !acceptKeyOutOfInputField(keyEvent)) + return false; + + Q_ASSERT(m_editCommand.empty()); + if (WebEventFactory::getEditCommand(keyEvent, &m_editCommand) + || isCommonTextEditShortcut(keyEvent)) { + event->accept(); + return true; + } + + return false; + } case QEvent::MouseButtonPress: Focus(); // Fall through. case QEvent::MouseButtonRelease: @@ -973,8 +1080,16 @@ bool RenderWidgetHostViewQt::forwardEvent(QEvent *event) QVariant RenderWidgetHostViewQt::inputMethodQuery(Qt::InputMethodQuery query) { switch (query) { - case Qt::ImEnabled: - return QVariant(getTextInputType() != ui::TEXT_INPUT_TYPE_NONE); + case Qt::ImEnabled: { + ui::TextInputType type = getTextInputType(); + bool editorVisible = type != ui::TEXT_INPUT_TYPE_NONE; + // IME manager should disable composition on input fields with ImhHiddenText hint if supported + if (m_imeHasHiddenTextCapability) + return QVariant(editorVisible); + + bool passwordInput = type == ui::TEXT_INPUT_TYPE_PASSWORD; + return QVariant(editorVisible && !passwordInput); + } case Qt::ImFont: // TODO: Implement this return QVariant(); @@ -1010,17 +1125,16 @@ QVariant RenderWidgetHostViewQt::inputMethodQuery(Qt::InputMethodQuery query) void RenderWidgetHostViewQt::ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch, content::InputEventAckState ack_result) { Q_UNUSED(touch); const bool eventConsumed = ack_result == content::INPUT_EVENT_ACK_STATE_CONSUMED; - m_gestureProvider.OnTouchEventAck(touch.event.uniqueTouchEventId, eventConsumed); + m_gestureProvider.OnTouchEventAck(touch.event.unique_touch_event_id, eventConsumed, /*fixme: ?? */false); } void RenderWidgetHostViewQt::sendDelegatedFrameAck() { - m_beginFrameSource->DidFinishFrame(this, 0); - cc::ReturnedResourceArray resources; + m_beginFrameSource->DidFinishFrame(this); + std::vector<cc::ReturnedResource> resources; m_resourcesToRelease.swap(resources); - content::RenderWidgetHostImpl::SendReclaimCompositorResources( - m_host->GetRoutingID(), m_pendingOutputSurfaceId, - m_host->GetProcess()->GetID(), true, resources); + if (m_rendererCompositorFrameSink) + m_rendererCompositorFrameSink->DidReceiveCompositorFrameAck(resources); } void RenderWidgetHostViewQt::processMotionEvent(const ui::MotionEvent &motionEvent) @@ -1060,7 +1174,7 @@ float RenderWidgetHostViewQt::dpiScale() const bool RenderWidgetHostViewQt::IsPopup() const { - return popup_type_ != blink::WebPopupTypeNone; + return popup_type_ != blink::kWebPopupTypeNone; } void RenderWidgetHostViewQt::handleMouseEvent(QMouseEvent* event) @@ -1073,8 +1187,8 @@ void RenderWidgetHostViewQt::handleMouseEvent(QMouseEvent* event) return; blink::WebMouseEvent webEvent = WebEventFactory::toWebMouseEvent(event, dpiScale()); - if ((webEvent.type == blink::WebInputEvent::MouseDown || webEvent.type == blink::WebInputEvent::MouseUp) - && webEvent.button == blink::WebMouseEvent::Button::NoButton) { + if ((webEvent.GetType() == blink::WebInputEvent::kMouseDown || webEvent.GetType() == blink::WebInputEvent::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. return; } @@ -1083,17 +1197,18 @@ void RenderWidgetHostViewQt::handleMouseEvent(QMouseEvent* event) if (event->type() == QMouseEvent::MouseButtonPress) { 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()) + || (event->pos() - m_clickHelper.lastPressPosition).manhattanLength() > qGuiApp->styleHints()->startDragDistance() + || m_clickHelper.clickCounter >= 3) m_clickHelper.clickCounter = 0; m_clickHelper.lastPressTimestamp = event->timestamp(); - webEvent.clickCount = ++m_clickHelper.clickCounter; + webEvent.click_count = ++m_clickHelper.clickCounter; m_clickHelper.lastPressButton = event->button(); m_clickHelper.lastPressPosition = QPointF(event->pos()).toPoint(); } - webEvent.movementX = event->globalX() - m_previousMousePosition.x(); - webEvent.movementY = event->globalY() - m_previousMousePosition.y(); + webEvent.movement_x = event->globalX() - m_previousMousePosition.x(); + webEvent.movement_y = event->globalY() - m_previousMousePosition.y(); if (IsMouseLocked()) QCursor::setPos(m_previousMousePosition); @@ -1132,7 +1247,7 @@ void RenderWidgetHostViewQt::handleKeyEvent(QKeyEvent *ev) if (ev->type() == QEvent::KeyRelease) { m_receivedEmptyImeText = false; m_host->ImeSetComposition(toString16(ev->text()), - std::vector<blink::WebCompositionUnderline>(), + std::vector<ui::CompositionUnderline>(), gfx::Range::InvalidRange(), gfx::Range::InvalidRange().start(), gfx::Range::InvalidRange().end()); @@ -1144,7 +1259,17 @@ void RenderWidgetHostViewQt::handleKeyEvent(QKeyEvent *ev) } content::NativeWebKeyboardEvent webEvent = WebEventFactory::toWebKeyboardEvent(ev); - bool keyDownTextInsertion = webEvent.type == blink::WebInputEvent::RawKeyDown && webEvent.text[0]; + if (webEvent.GetType() == blink::WebInputEvent::kRawKeyDown && !m_editCommand.empty()) { + ui::LatencyInfo latency; + latency.set_source_event_type(ui::SourceEventType::KEY_PRESS); + content::EditCommands commands; + commands.emplace_back(m_editCommand, ""); + m_editCommand.clear(); + m_host->ForwardKeyboardEventWithCommands(webEvent, latency, &commands, nullptr); + return; + } + + bool keyDownTextInsertion = webEvent.GetType() == blink::WebInputEvent::kRawKeyDown && webEvent.text[0]; webEvent.skip_in_browser = keyDownTextInsertion; m_host->ForwardKeyboardEvent(webEvent); @@ -1153,7 +1278,7 @@ void RenderWidgetHostViewQt::handleKeyEvent(QKeyEvent *ev) // 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.type = blink::WebInputEvent::Char; + webEvent.SetType(blink::WebInputEvent::kChar); m_host->ForwardKeyboardEvent(webEvent); } } @@ -1173,7 +1298,7 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev) gfx::Range selectionRange = gfx::Range::InvalidRange(); const QList<QInputMethodEvent::Attribute> &attributes = ev->attributes(); - std::vector<blink::WebCompositionUnderline> underlines; + std::vector<ui::CompositionUnderline> underlines; bool hasSelection = false; for (const auto &attribute : attributes) { @@ -1198,7 +1323,7 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev) if (format.underlineStyle() != QTextCharFormat::NoUnderline) underlineColor = format.underlineColor(); - underlines.push_back(blink::WebCompositionUnderline(start, end, toSk(underlineColor), /*thick*/ false, SK_ColorTRANSPARENT)); + underlines.push_back(ui::CompositionUnderline(start, end, toSk(underlineColor), /*thick*/ false, SK_ColorTRANSPARENT)); break; } case QInputMethodEvent::Cursor: @@ -1237,9 +1362,9 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev) } if (hasSelection) { - content::RenderFrameHost *frameHost = getFocusedFrameHost(); + content::RenderFrameHostImpl *frameHost = static_cast<content::RenderFrameHostImpl *>(getFocusedFrameHost()); if (frameHost) - frameHost->Send(new InputMsg_SetEditableSelectionOffsets(frameHost->GetRoutingID(), selectionRange.start(), selectionRange.end())); + frameHost->GetFrameInputHandler()->SetEditableSelectionOffsets(selectionRange.start(), selectionRange.end()); } int replacementLength = ev->replacementLength(); @@ -1333,7 +1458,28 @@ void RenderWidgetHostViewQt::accessibilityActiveChanged(bool active) void RenderWidgetHostViewQt::handleWheelEvent(QWheelEvent *ev) { - m_host->ForwardWheelEvent(WebEventFactory::toWebWheelEvent(ev, dpiScale())); + if (!m_wheelAckPending) { + Q_ASSERT(m_pendingWheelEvents.isEmpty()); + m_wheelAckPending = true; + m_host->ForwardWheelEvent(WebEventFactory::toWebWheelEvent(ev, dpiScale())); + return; + } + if (!m_pendingWheelEvents.isEmpty()) { + // Try to combine with this wheel event with the last pending one. + if (WebEventFactory::coalesceWebWheelEvent(m_pendingWheelEvents.last(), ev, dpiScale())) + return; + } + m_pendingWheelEvents.append(WebEventFactory::toWebWheelEvent(ev, dpiScale())); +} + +void RenderWidgetHostViewQt::WheelEventAck(const blink::WebMouseWheelEvent &/*event*/, content::InputEventAckState /*ack_result*/) +{ + m_wheelAckPending = false; + if (!m_pendingWheelEvents.isEmpty()) { + m_wheelAckPending = true; + m_host->ForwardWheelEvent(m_pendingWheelEvents.takeFirst()); + } + // TODO: We could forward unhandled wheelevents to our parent. } void RenderWidgetHostViewQt::clearPreviousTouchMotionState() @@ -1512,7 +1658,10 @@ void RenderWidgetHostViewQt::updateNeedsBeginFramesInternal() bool RenderWidgetHostViewQt::OnBeginFrameDerivedImpl(const cc::BeginFrameArgs& args) { m_beginFrameSource->OnUpdateVSyncParameters(args.frame_time, args.interval); - m_host->Send(new ViewMsg_BeginFrame(m_host->GetRoutingID(), args)); + if (m_rendererCompositorFrameSink) + m_rendererCompositorFrameSink->OnBeginFrame(args); + else // FIXME: is this else part ever needed? + m_host->Send(new ViewMsg_BeginFrame(m_host->GetRoutingID(), args)); return true; } diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h index ae3ce610c..8a7665007 100644 --- a/src/core/render_widget_host_view_qt.h +++ b/src/core/render_widget_host_view_qt.h @@ -138,6 +138,7 @@ public: void Hide() override; bool IsShowing() override; gfx::Rect GetViewBounds() const override; + SkColor background_color() const override; void SetBackgroundColor(SkColor color) override; bool LockMouse() override; void UnlockMouse() override; @@ -148,19 +149,15 @@ public: void RenderProcessGone(base::TerminationStatus, int) override; void Destroy() override; void SetTooltipText(const base::string16 &tooltip_text) override; - void CopyFromCompositingSurface(const gfx::Rect& src_subrect, const gfx::Size& dst_size, const content::ReadbackRequestCallback& callback, const SkColorType preferred_color_type) override; - void CopyFromCompositingSurfaceToVideoFrame(const gfx::Rect& src_subrect, const scoped_refptr<media::VideoFrame>& target, const base::Callback<void(const gfx::Rect&, bool)>& callback) override; - - bool CanCopyToVideoFrame() const override; bool HasAcceleratedSurface(const gfx::Size&) override; - void OnSwapCompositorFrame(uint32_t output_surface_id, cc::CompositorFrame frame) override; + void DidCreateNewRendererCompositorFrameSink(cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) override; + void SubmitCompositorFrame(const viz::LocalSurfaceId&, cc::CompositorFrame) override; + void WheelEventAck(const blink::WebMouseWheelEvent &event, content::InputEventAckState ack_result) override; void GetScreenInfo(content::ScreenInfo* results); gfx::Rect GetBoundsInRootWindow() override; void ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch, content::InputEventAckState ack_result) override; void ClearCompositorFrame() override; - void LockCompositingSurface() override; - void UnlockCompositingSurface() override; void SetNeedsBeginFrames(bool needs_begin_frames) override; // Overridden from ui::GestureProviderClient. @@ -242,14 +239,14 @@ private: std::unique_ptr<RenderWidgetHostViewQtDelegate> m_delegate; QExplicitlySharedDataPointer<ChromiumCompositorData> m_chromiumCompositorData; - cc::ReturnedResourceArray m_resourcesToRelease; + std::vector<cc::ReturnedResource> m_resourcesToRelease; bool m_needsDelegatedFrameAck; LoadVisuallyCommittedState m_loadVisuallyCommittedState; - uint32_t m_pendingOutputSurfaceId; QMetaObject::Connection m_adapterClientDestroyedConnection; WebContentsAdapterClient *m_adapterClient; MultipleMouseClickHelper m_clickHelper; + cc::mojom::CompositorFrameSinkClient *m_rendererCompositorFrameSink; bool m_imeInProgress; bool m_receivedEmptyImeText; @@ -263,6 +260,8 @@ private: gfx::Vector2dF m_lastScrollOffset; gfx::SizeF m_lastContentsSize; + SkColor m_backgroundColor; + viz::LocalSurfaceId m_localSurfaceId; uint m_imState; int m_anchorPositionWithinSelection; @@ -270,6 +269,13 @@ private: uint m_cursorPosition; bool m_emptyPreviousSelection; QString m_surroundingText; + + bool m_imeHasHiddenTextCapability; + + bool m_wheelAckPending; + QList<blink::WebMouseWheelEvent> m_pendingWheelEvents; + + std::string m_editCommand; }; } // namespace QtWebEngineCore diff --git a/src/core/render_widget_host_view_qt_delegate.cpp b/src/core/render_widget_host_view_qt_delegate.cpp deleted file mode 100644 index a86900433..000000000 --- a/src/core/render_widget_host_view_qt_delegate.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 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 "render_widget_host_view_qt_delegate.h" - -#include <QtCore/qvariant.h> -#include <QtGui/qevent.h> - -#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) -#include <QtGui/private/qinputcontrol_p.h> -#endif - -static bool isCommonTextEditShortcut(const QKeyEvent *ke) -{ -#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) - return QInputControl::isCommonTextEditShortcut(ke); -#else - if (ke->modifiers() == Qt::NoModifier - || ke->modifiers() == Qt::ShiftModifier - || ke->modifiers() == Qt::KeypadModifier) { - if (ke->key() < Qt::Key_Escape) { - return true; - } else { - switch (ke->key()) { - case Qt::Key_Return: - case Qt::Key_Enter: - case Qt::Key_Delete: - case Qt::Key_Home: - case Qt::Key_End: - case Qt::Key_Backspace: - case Qt::Key_Left: - case Qt::Key_Right: - case Qt::Key_Up: - case Qt::Key_Down: - case Qt::Key_Tab: - return true; - default: - break; - } - } - } else if (ke->matches(QKeySequence::Copy) - || ke->matches(QKeySequence::Paste) - || ke->matches(QKeySequence::Cut) - || ke->matches(QKeySequence::Redo) - || ke->matches(QKeySequence::Undo) - || ke->matches(QKeySequence::MoveToNextWord) - || ke->matches(QKeySequence::MoveToPreviousWord) - || ke->matches(QKeySequence::MoveToStartOfDocument) - || ke->matches(QKeySequence::MoveToEndOfDocument) - || ke->matches(QKeySequence::SelectNextWord) - || ke->matches(QKeySequence::SelectPreviousWord) - || ke->matches(QKeySequence::SelectStartOfLine) - || ke->matches(QKeySequence::SelectEndOfLine) - || ke->matches(QKeySequence::SelectStartOfBlock) - || ke->matches(QKeySequence::SelectEndOfBlock) - || ke->matches(QKeySequence::SelectStartOfDocument) - || ke->matches(QKeySequence::SelectEndOfDocument) - || ke->matches(QKeySequence::SelectAll) - ) { - return true; - } - return false; -#endif -} - -namespace QtWebEngineCore { - -bool RenderWidgetHostViewQtDelegateClient::handleShortcutOverrideEvent(QKeyEvent *event) -{ - if (inputMethodQuery(Qt::ImEnabled).toBool() && isCommonTextEditShortcut(event)) { - event->accept(); - return true; - } - return false; -} - -} // 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 dda59a01a..bcd0f49f7 100644 --- a/src/core/render_widget_host_view_qt_delegate.h +++ b/src/core/render_widget_host_view_qt_delegate.h @@ -48,7 +48,6 @@ QT_BEGIN_NAMESPACE class QCursor; class QEvent; -class QKeyEvent; class QPainter; class QSGLayer; class QSGNode; @@ -58,16 +57,9 @@ class QVariant; class QWindow; class QInputMethodEvent; -#if (QT_VERSION < QT_VERSION_CHECK(5, 8, 0)) -class QSGImageNode; -typedef QSGImageNode QSGInternalImageNode; -class QSGSimpleTextureNode; -typedef QSGSimpleTextureNode QSGTextureNode; -#else class QSGInternalImageNode; class QSGImageNode; typedef QSGImageNode QSGTextureNode; -#endif QT_END_NAMESPACE @@ -86,7 +78,6 @@ public: virtual void windowChanged() = 0; virtual bool forwardEvent(QEvent *) = 0; virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) = 0; - virtual bool handleShortcutOverrideEvent(QKeyEvent *event); }; class QWEBENGINE_EXPORT RenderWidgetHostViewQtDelegate { @@ -113,7 +104,7 @@ public: virtual void updateCursor(const QCursor &) = 0; virtual void resize(int width, int height) = 0; virtual void move(const QPoint &) = 0; - virtual void inputMethodStateChanged(bool editorVisible) = 0; + virtual void inputMethodStateChanged(bool editorVisible, bool passwordInput) = 0; virtual void setInputMethodHints(Qt::InputMethodHints hints) = 0; virtual void setClearColor(const QColor &color) = 0; }; diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp index ac6d7a2dc..5980d7b84 100644 --- a/src/core/renderer/content_renderer_client_qt.cpp +++ b/src/core/renderer/content_renderer_client_qt.cpp @@ -57,13 +57,15 @@ #include "components/visitedlink/renderer/visitedlink_slave.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/renderer/render_thread.h" #include "content/public/renderer/render_view.h" #include "net/base/net_errors.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/platform/WebURLError.h" #include "third_party/WebKit/public/platform/WebURLRequest.h" -#include "third_party/WebKit/public/web/WebSecurityPolicy.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/webui/jstemplate_builder.h" #include "content/public/common/web_preferences.h" @@ -76,7 +78,7 @@ #include "renderer/render_view_observer_qt.h" #include "renderer/user_resource_controller.h" #include "renderer/web_channel_ipc_transport.h" -#include "services/service_manager/public/cpp/interface_registry.h" +#include "services/service_manager/public/cpp/binder_registry.h" #include "components/grit/components_resources.h" @@ -85,7 +87,6 @@ namespace QtWebEngineCore { static const char kHttpErrorDomain[] = "http"; -static const char kQrcSchemeQt[] = "qrc"; ContentRendererClientQt::ContentRendererClientQt() { @@ -100,18 +101,22 @@ void ContentRendererClientQt::RenderThreadStarted() content::RenderThread *renderThread = content::RenderThread::Get(); m_visitedLinkSlave.reset(new visitedlink::VisitedLinkSlave); m_webCacheImpl.reset(new web_cache::WebCacheImpl()); - renderThread->GetInterfaceRegistry()->AddInterface( - m_visitedLinkSlave->GetBindCallback()); + + auto registry = base::MakeUnique<service_manager::BinderRegistry>(); + registry->AddInterface(m_visitedLinkSlave->GetBindCallback(), + base::ThreadTaskRunnerHandle::Get()); + content::ChildThread::Get() + ->GetServiceManagerConnection() + ->AddConnectionFilter(base::MakeUnique<content::SimpleConnectionFilter>( + std::move(registry))); + + renderThread->AddObserver(UserResourceController::instance()); #if BUILDFLAG(ENABLE_SPELLCHECK) m_spellCheck.reset(new SpellCheck()); renderThread->AddObserver(m_spellCheck.data()); #endif - - blink::WebString qrcScheme(base::ASCIIToUTF16(kQrcSchemeQt)); - // mark qrc as a secure scheme (avoids deprecation warnings) - blink::WebSecurityPolicy::registerURLSchemeAsSecure(qrcScheme); } void ContentRendererClientQt::RenderViewCreated(content::RenderView* render_view) @@ -120,15 +125,16 @@ void ContentRendererClientQt::RenderViewCreated(content::RenderView* render_view new RenderViewObserverQt(render_view, m_webCacheImpl.data()); new WebChannelIPCTransport(render_view); UserResourceController::instance()->renderViewCreated(render_view); -#if BUILDFLAG(ENABLE_SPELLCHECK) - new SpellCheckProvider(render_view, m_spellCheck.data()); -#endif - } void ContentRendererClientQt::RenderFrameCreated(content::RenderFrame* render_frame) { new QtWebEngineCore::RenderFrameObserverQt(render_frame); + UserResourceController::instance()->renderFrameCreated(render_frame); + +#if BUILDFLAG(ENABLE_SPELLCHECK) + new SpellCheckProvider(render_frame, m_spellCheck.data()); +#endif #if BUILDFLAG(ENABLE_BASIC_PRINTING) new printing::PrintWebViewHelper( render_frame, @@ -179,7 +185,7 @@ bool ContentRendererClientQt::ShouldSuppressErrorPage(content::RenderFrame *fram // To tap into the chromium localized strings. Ripped from the chrome layer (highly simplified). void ContentRendererClientQt::GetNavigationErrorStrings(content::RenderFrame* renderFrame, const blink::WebURLRequest &failedRequest, const blink::WebURLError &error, std::string *errorHtml, base::string16 *errorDescription) { - const bool isPost = QByteArray::fromStdString(failedRequest.httpMethod().utf8()) == QByteArrayLiteral("POST"); + const bool isPost = QByteArray::fromStdString(failedRequest.HttpMethod().Utf8()) == QByteArrayLiteral("POST"); if (errorHtml) { // Use a local error page. @@ -190,8 +196,8 @@ void ContentRendererClientQt::GetNavigationErrorStrings(content::RenderFrame* re // TODO(elproxy): We could potentially get better diagnostics here by first calling // NetErrorHelper::GetErrorStringsForDnsProbe, but that one is harder to untangle. - error_page::LocalizedError::GetStrings(error.reason, error.domain.utf8(), error.unreachableURL, isPost - , error.staleCopyInCache && !isPost, false, false, locale + error_page::LocalizedError::GetStrings(error.reason, error.domain.Utf8(), error.unreachable_url, isPost + , error.stale_copy_in_cache && !isPost, false, false, locale , std::unique_ptr<error_page::ErrorPageParams>(), &errorStrings); resourceId = IDR_NET_ERROR_HTML; @@ -204,7 +210,7 @@ void ContentRendererClientQt::GetNavigationErrorStrings(content::RenderFrame* re } if (errorDescription) - *errorDescription = error_page::LocalizedError::GetErrorDetails(error.domain.utf8(), error.reason, isPost); + *errorDescription = error_page::LocalizedError::GetErrorDetails(error.domain.Utf8(), error.reason, isPost); } unsigned long long ContentRendererClientQt::VisitedLinkHash(const char *canonicalUrl, size_t length) @@ -256,11 +262,11 @@ public: return true; case media::EmeInitDataType::CENC: -#if defined(USE_PROPRIETARY_CODECS) +#if BUILDFLAG(USE_PROPRIETARY_CODECS) return true; #else return false; -#endif // defined(USE_PROPRIETARY_CODECS) +#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) case media::EmeInitDataType::UNKNOWN: return false; @@ -271,7 +277,7 @@ public: media::SupportedCodecs GetSupportedCodecs() const override { -#if defined(USE_PROPRIETARY_CODECS) +#if BUILDFLAG(USE_PROPRIETARY_CODECS) return media::EME_CODEC_MP4_ALL | media::EME_CODEC_WEBM_ALL; #else return media::EME_CODEC_WEBM_ALL; @@ -384,10 +390,10 @@ static void AddPepperBasedWidevine(std::vector<std::unique_ptr<media::KeySystemP supported_codecs |= media::EME_CODEC_WEBM_VORBIS; supported_codecs |= media::EME_CODEC_WEBM_VP8; supported_codecs |= media::EME_CODEC_WEBM_VP9; -#if defined(USE_PROPRIETARY_CODECS) +#if BUILDFLAG(USE_PROPRIETARY_CODECS) supported_codecs |= media::EME_CODEC_MP4_AVC1; supported_codecs |= media::EME_CODEC_MP4_AAC; -#endif // defined(USE_PROPRIETARY_CODECS) +#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) using Robustness = cdm::WidevineKeySystemProperties::Robustness; concrete_key_systems->emplace_back(new cdm::WidevineKeySystemProperties( diff --git a/src/core/renderer/pepper/pepper_flash_renderer_host_qt.cpp b/src/core/renderer/pepper/pepper_flash_renderer_host_qt.cpp index ca3ef9dda..bac1d7c1f 100644 --- a/src/core/renderer/pepper/pepper_flash_renderer_host_qt.cpp +++ b/src/core/renderer/pepper/pepper_flash_renderer_host_qt.cpp @@ -48,7 +48,8 @@ #include <vector> #include "base/lazy_instance.h" -#include "base/metrics/histogram.h" +#include "base/macros.h" +#include "base/metrics/histogram_macros.h" #include "base/strings/string_util.h" #include "content/public/renderer/pepper_plugin_instance.h" #include "content/public/renderer/render_thread.h" @@ -137,8 +138,8 @@ enum FlashNavigateUsage { FLASH_NAVIGATE_USAGE_ENUM_COUNT }; -static base::LazyInstance<std::map<std::string, FlashNavigateUsage> > -g_rejected_headers = LAZY_INSTANCE_INITIALIZER; +static base::LazyInstance<std::map<std::string, FlashNavigateUsage>>:: + DestructorAtExit g_rejected_headers = LAZY_INSTANCE_INITIALIZER; bool IsSimpleHeader(const std::string& lower_case_header_name, const std::string& header_value) diff --git a/src/core/renderer/render_frame_observer_qt.cpp b/src/core/renderer/render_frame_observer_qt.cpp index 45d45c739..727bf5b92 100644 --- a/src/core/renderer/render_frame_observer_qt.cpp +++ b/src/core/renderer/render_frame_observer_qt.cpp @@ -64,7 +64,11 @@ RenderFrameObserverQt::~RenderFrameObserverQt() { } -#if defined(ENABLE_PLUGINS) +void RenderFrameObserverQt::OnDestruct() { + delete this; +} + +#if BUILDFLAG(ENABLE_PLUGINS) void RenderFrameObserverQt::DidCreatePepperPlugin(content::RendererPpapiHost* host) { host->GetPpapiHost()->AddHostFactoryFilter( diff --git a/src/core/renderer/render_frame_observer_qt.h b/src/core/renderer/render_frame_observer_qt.h index b74be5cd1..ac098a961 100644 --- a/src/core/renderer/render_frame_observer_qt.h +++ b/src/core/renderer/render_frame_observer_qt.h @@ -43,6 +43,7 @@ #include "base/compiler_specific.h" #include "content/public/renderer/render_frame_observer.h" #include "content/public/renderer/render_frame_observer_tracker.h" +#include "ppapi/features/features.h" namespace content { @@ -59,10 +60,10 @@ public: explicit RenderFrameObserverQt(content::RenderFrame* render_frame); ~RenderFrameObserverQt(); -#if defined(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PLUGINS) void DidCreatePepperPlugin(content::RendererPpapiHost* host) override; #endif - void OnDestruct() override { } + void OnDestruct() override; void FrameDetached() override; bool isFrameDetached() const; diff --git a/src/core/renderer/render_view_observer_qt.cpp b/src/core/renderer/render_view_observer_qt.cpp index 97485afad..4893a5188 100644 --- a/src/core/renderer/render_view_observer_qt.cpp +++ b/src/core/renderer/render_view_observer_qt.cpp @@ -62,25 +62,30 @@ RenderViewObserverQt::RenderViewObserverQt( void RenderViewObserverQt::onFetchDocumentMarkup(quint64 requestId) { 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)); + 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())); } void RenderViewObserverQt::onFetchDocumentInnerText(quint64 requestId) { blink::WebString text; - if (render_view()->GetWebView()->mainFrame()->isWebLocalFrame()) - text = blink::WebFrameContentDumper::dumpWebViewAsText( + 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)); + Send(new RenderViewObserverHostQt_DidFetchDocumentInnerText(routing_id(), requestId, text.Utf16())); } void RenderViewObserverQt::onSetBackgroundColor(quint32 color) { - render_view()->GetWebFrameWidget()->setBaseBackgroundColor(color); + render_view()->GetWebFrameWidget()->SetBaseBackgroundColor(color); +} + +void RenderViewObserverQt::OnDestruct() +{ + delete this; } bool RenderViewObserverQt::OnMessageReceived(const IPC::Message& message) diff --git a/src/core/renderer/render_view_observer_qt.h b/src/core/renderer/render_view_observer_qt.h index 60b11c428..abb472f02 100644 --- a/src/core/renderer/render_view_observer_qt.h +++ b/src/core/renderer/render_view_observer_qt.h @@ -57,7 +57,7 @@ private: void onFetchDocumentInnerText(quint64 requestId); void onSetBackgroundColor(quint32 color); - void OnDestruct() override { } + void OnDestruct() override; bool OnMessageReceived(const IPC::Message& message) override; void Navigate(const GURL& url) override; diff --git a/src/core/renderer/user_resource_controller.cpp b/src/core/renderer/user_resource_controller.cpp index 36125d189..f85879053 100644 --- a/src/core/renderer/user_resource_controller.cpp +++ b/src/core/renderer/user_resource_controller.cpp @@ -39,10 +39,12 @@ #include "user_resource_controller.h" +#include "base/memory/weak_ptr.h" #include "base/pending_task.h" #include "base/strings/pattern.h" #include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_view.h" +#include "content/public/renderer/render_frame_observer.h" #include "content/public/renderer/render_view_observer.h" #include "extensions/common/url_pattern.h" #include "third_party/WebKit/public/web/WebDocument.h" @@ -97,16 +99,19 @@ static bool scriptMatchesURL(const UserScriptData &scriptData, const GURL &url) return true; } -class UserResourceController::RenderViewObserverHelper : public content::RenderViewObserver +class UserResourceController::RenderFrameObserverHelper : public content::RenderFrameObserver { public: - RenderViewObserverHelper(content::RenderView *); + RenderFrameObserverHelper(content::RenderFrame* render_frame); + private: - // RenderViewObserver implementation. - void DidFinishDocumentLoad(blink::WebLocalFrame* frame) override; - void DidFinishLoad(blink::WebLocalFrame* frame) override; - void DidStartProvisionalLoad(blink::WebLocalFrame* frame) override; - void FrameDetached(blink::WebFrame* frame) override; + ~RenderFrameObserverHelper() override; + + // RenderFrameObserver implementation. + void DidFinishDocumentLoad() override; + void DidFinishLoad() override; + void DidStartProvisionalLoad(blink::WebDataSource* data_source) override; + void FrameDetached() override; void OnDestruct() override; bool OnMessageReceived(const IPC::Message& message) override; @@ -115,10 +120,24 @@ private: void onScriptsCleared(); void runScripts(UserScriptData::InjectionPoint, blink::WebLocalFrame *); + + // Set of frames which are pending to get an AfterLoad invocation of runScripts, if they + // haven't gotten it already. QSet<blink::WebLocalFrame *> m_pendingFrames; + base::WeakPtrFactory<RenderFrameObserverHelper> m_weakPtrFactory; +}; + +// 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::RenderViewObserverHelper::runScripts(UserScriptData::InjectionPoint p, blink::WebLocalFrame *frame) +void UserResourceController::RenderFrameObserverHelper::runScripts(UserScriptData::InjectionPoint p, blink::WebLocalFrame *frame) { if (p == UserScriptData::AfterLoad && !m_pendingFrames.remove(frame)) return; @@ -128,12 +147,16 @@ void UserResourceController::RenderViewObserverHelper::runScripts(UserScriptData void UserResourceController::runScripts(UserScriptData::InjectionPoint p, blink::WebLocalFrame *frame) { - content::RenderView *renderView = content::RenderView::FromWebView(frame->view()); + content::RenderFrame *renderFrame = content::RenderFrame::FromWebFrame(frame); + if (!renderFrame) + return; + const bool isMainFrame = renderFrame->IsMainFrame(); + + content::RenderView *renderView = renderFrame->GetRenderView(); if (!renderView) return; - const bool isMainFrame = (frame == renderView->GetWebView()->mainFrame()); - QList<uint64_t> scriptsToRun = m_viewUserScriptMap.value(globalScriptsIndex).toList(); + QList<uint64_t> scriptsToRun = m_viewUserScriptMap.value(0).toList(); scriptsToRun.append(m_viewUserScriptMap.value(renderView).toList()); Q_FOREACH (uint64_t id, scriptsToRun) { @@ -141,13 +164,13 @@ void UserResourceController::runScripts(UserScriptData::InjectionPoint p, blink: if (script.injectionPoint != p || (!script.injectForSubframes && !isMainFrame)) continue; - if (!scriptMatchesURL(script, frame->document().url())) + if (!scriptMatchesURL(script, frame->GetDocument().Url())) continue; - blink::WebScriptSource source(blink::WebString::fromUTF8(script.source), script.url); + blink::WebScriptSource source(blink::WebString::FromUTF8(script.source), script.url); if (script.worldId) - frame->executeScriptInIsolatedWorld(script.worldId, &source, /*numSources = */1, /*contentScriptExtentsionGroup = */ 0); + frame->ExecuteScriptInIsolatedWorld(script.worldId, &source, /*numSources = */1, /*contentScriptExtentsionGroup = */ 0); else - frame->executeScript(source); + frame->ExecuteScript(source); } } @@ -161,71 +184,96 @@ void UserResourceController::RunScriptsAtDocumentEnd(content::RenderFrame *rende runScripts(UserScriptData::DocumentLoadFinished, render_frame->GetWebFrame()); } -UserResourceController::RenderViewObserverHelper::RenderViewObserverHelper(content::RenderView *renderView) - : content::RenderViewObserver(renderView) +UserResourceController::RenderFrameObserverHelper::RenderFrameObserverHelper(content::RenderFrame *render_frame) + : content::RenderFrameObserver(render_frame), m_weakPtrFactory(this) +{ +} + +UserResourceController::RenderFrameObserverHelper::~RenderFrameObserverHelper() +{ + m_weakPtrFactory.InvalidateWeakPtrs(); +} + +UserResourceController::RenderViewObserverHelper::RenderViewObserverHelper(content::RenderView *render_view) + : content::RenderViewObserver(render_view) { } -void UserResourceController::RenderViewObserverHelper::DidFinishDocumentLoad(blink::WebLocalFrame *frame) +void UserResourceController::RenderFrameObserverHelper::DidFinishDocumentLoad() { + blink::WebLocalFrame *frame = render_frame()->GetWebFrame(); m_pendingFrames.insert(frame); - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE, base::Bind(&UserResourceController::RenderViewObserverHelper::runScripts, - base::Unretained(this), UserScriptData::AfterLoad, frame), + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE, base::Bind(&UserResourceController::RenderFrameObserverHelper::runScripts, + m_weakPtrFactory.GetWeakPtr(), UserScriptData::AfterLoad, frame), base::TimeDelta::FromMilliseconds(afterLoadTimeout)); } -void UserResourceController::RenderViewObserverHelper::DidFinishLoad(blink::WebLocalFrame *frame) +void UserResourceController::RenderFrameObserverHelper::DidFinishLoad() { + blink::WebLocalFrame *frame = render_frame()->GetWebFrame(); + // DidFinishDocumentLoad always comes before this, so frame has already been marked as pending. - base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::Bind(&UserResourceController::RenderViewObserverHelper::runScripts, - base::Unretained(this), UserScriptData::AfterLoad, frame)); + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::Bind(&UserResourceController::RenderFrameObserverHelper::runScripts, + m_weakPtrFactory.GetWeakPtr(), UserScriptData::AfterLoad, frame)); +} + +void UserResourceController::RenderFrameObserverHelper::DidStartProvisionalLoad(blink::WebDataSource *data_source) +{ + Q_UNUSED(data_source); + blink::WebLocalFrame *frame = render_frame()->GetWebFrame(); + m_pendingFrames.remove(frame); } -void UserResourceController::RenderViewObserverHelper::DidStartProvisionalLoad(blink::WebLocalFrame *frame) +void UserResourceController::RenderFrameObserverHelper::FrameDetached() { + blink::WebLocalFrame *frame = render_frame()->GetWebFrame(); m_pendingFrames.remove(frame); } -void UserResourceController::RenderViewObserverHelper::FrameDetached(blink::WebFrame *frame) +void UserResourceController::RenderFrameObserverHelper::OnDestruct() { - if (frame->isWebLocalFrame()) - m_pendingFrames.remove(frame->toWebLocalFrame()); + 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::RenderViewObserverHelper::OnMessageReceived(const IPC::Message &message) +bool UserResourceController::RenderFrameObserverHelper::OnMessageReceived(const IPC::Message &message) { bool handled = true; - IPC_BEGIN_MESSAGE_MAP(UserResourceController::RenderViewObserverHelper, message) - IPC_MESSAGE_HANDLER(RenderViewObserverHelper_AddScript, onUserScriptAdded) - IPC_MESSAGE_HANDLER(RenderViewObserverHelper_RemoveScript, onUserScriptRemoved) - IPC_MESSAGE_HANDLER(RenderViewObserverHelper_ClearScripts, onScriptsCleared) + 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::RenderViewObserverHelper::onUserScriptAdded(const UserScriptData &script) +void UserResourceController::RenderFrameObserverHelper::onUserScriptAdded(const UserScriptData &script) { - if (content::RenderView *view = render_view()) - UserResourceController::instance()->addScriptForView(script, view); + if (content::RenderFrame *frame = render_frame()) + if (content::RenderView *view = frame->GetRenderView()) + UserResourceController::instance()->addScriptForView(script, view); } -void UserResourceController::RenderViewObserverHelper::onUserScriptRemoved(const UserScriptData &script) +void UserResourceController::RenderFrameObserverHelper::onUserScriptRemoved(const UserScriptData &script) { - if (content::RenderView *view = render_view()) - UserResourceController::instance()->removeScriptForView(script, view); + if (content::RenderFrame *frame = render_frame()) + if (content::RenderView *view = frame->GetRenderView()) + UserResourceController::instance()->removeScriptForView(script, view); } -void UserResourceController::RenderViewObserverHelper::onScriptsCleared() +void UserResourceController::RenderFrameObserverHelper::onScriptsCleared() { - if (content::RenderView *view = render_view()) - UserResourceController::instance()->clearScriptsForView(view); + if (content::RenderFrame *frame = render_frame()) + if (content::RenderView *view = frame->GetRenderView()) + UserResourceController::instance()->clearScriptsForView(view); } UserResourceController *UserResourceController::instance() @@ -254,9 +302,15 @@ UserResourceController::UserResourceController() #endif // !defined(QT_NO_DEBUG) || defined(QT_FORCE_ASSERTS) } +void UserResourceController::renderFrameCreated(content::RenderFrame *renderFrame) +{ + // Will destroy itself when the RenderFrame is destroyed. + new RenderFrameObserverHelper(renderFrame); +} + void UserResourceController::renderViewCreated(content::RenderView *renderView) { - // Will destroy itself with their RenderView. + // Will destroy itself when the RenderView is destroyed. new RenderViewObserverHelper(renderView); } diff --git a/src/core/renderer/user_resource_controller.h b/src/core/renderer/user_resource_controller.h index 5d412fe40..50af24243 100644 --- a/src/core/renderer/user_resource_controller.h +++ b/src/core/renderer/user_resource_controller.h @@ -61,8 +61,9 @@ class UserResourceController : public content::RenderThreadObserver { public: static UserResourceController *instance(); UserResourceController(); + void renderFrameCreated(content::RenderFrame *); void renderViewCreated(content::RenderView *); - void renderViewDestroyed(content::RenderView *); + void renderViewDestroyed(content::RenderView *renderView); void addScriptForView(const UserScriptData &, content::RenderView *); void removeScriptForView(const UserScriptData &, content::RenderView *); void clearScriptsForView(content::RenderView *); @@ -73,6 +74,7 @@ public: private: Q_DISABLE_COPY(UserResourceController) + class RenderFrameObserverHelper; class RenderViewObserverHelper; // RenderProcessObserver implementation. @@ -89,7 +91,7 @@ private: ViewUserScriptMap m_viewUserScriptMap; QHash<uint64_t, UserScriptData> m_scripts; - friend class RenderViewObserverHelper; + friend class RenderFrameObserverHelper; }; #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 865bfc243..94a7baa1d 100644 --- a/src/core/renderer/web_channel_ipc_transport.cpp +++ b/src/core/renderer/web_channel_ipc_transport.cpp @@ -68,25 +68,30 @@ private: WebChannelTransport() { } virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate *isolate) override; - void NativeQtSendMessage(gin::Arguments *args) + bool NativeQtSendMessage(gin::Arguments *args) { content::RenderView *renderView = GetRenderView(args->isolate()); if (!renderView || args->Length() != 1) - return; + return false; v8::Handle<v8::Value> val; args->GetNext(&val); if (!val->IsString() && !val->IsStringObject()) - return; + return false; v8::String::Utf8Value utf8(val->ToString()); QByteArray valueData(*utf8, utf8.length()); QJsonParseError error; QJsonDocument doc = QJsonDocument::fromJson(valueData, &error); - if (error.error != QJsonParseError::NoError) + if (error.error != QJsonParseError::NoError) { qWarning("%s %d: Parsing error: %s",__FILE__, __LINE__, qPrintable(error.errorString())); + return false; + } int size = 0; const char *rawData = doc.rawData(&size); + if (size == 0) + return false; renderView->Send(new WebChannelIPCTransportHost_SendMessage(renderView->GetRoutingID(), std::vector<char>(rawData, rawData + size))); + return true; } DISALLOW_COPY_AND_ASSIGN(WebChannelTransport); @@ -100,9 +105,9 @@ void WebChannelTransport::Install(blink::WebFrame *frame, uint worldId) v8::HandleScope handleScope(isolate); v8::Handle<v8::Context> context; if (worldId == 0) - context = frame->mainWorldScriptContext(); + context = frame->ToWebLocalFrame()->MainWorldScriptContext(); else - context = frame->toWebLocalFrame()->isolatedWorldScriptContext(worldId, 0); + context = frame->ToWebLocalFrame()->IsolatedWorldScriptContext(worldId); v8::Context::Scope contextScope(context); gin::Handle<WebChannelTransport> transport = gin::CreateHandle(isolate, new WebChannelTransport); @@ -121,9 +126,9 @@ void WebChannelTransport::Uninstall(blink::WebFrame *frame, uint worldId) v8::HandleScope handleScope(isolate); v8::Handle<v8::Context> context; if (worldId == 0) - context = frame->mainWorldScriptContext(); + context = frame->ToWebLocalFrame()->MainWorldScriptContext(); else - context = frame->toWebLocalFrame()->isolatedWorldScriptContext(worldId, 0); + context = frame->ToWebLocalFrame()->IsolatedWorldScriptContext(worldId); v8::Context::Scope contextScope(context); v8::Handle<v8::Object> global(context->Global()); @@ -140,12 +145,12 @@ gin::ObjectTemplateBuilder WebChannelTransport::GetObjectTemplateBuilder(v8::Iso content::RenderView *WebChannelTransport::GetRenderView(v8::Isolate *isolate) { - blink::WebLocalFrame *webframe = blink::WebLocalFrame::frameForContext(isolate->GetCurrentContext()); + blink::WebLocalFrame *webframe = blink::WebLocalFrame::FrameForContext(isolate->GetCurrentContext()); DCHECK(webframe) << "There should be an active frame since we just got a native function called."; if (!webframe) return 0; - blink::WebView *webview = webframe->view(); + blink::WebView *webview = webframe->View(); if (!webview) return 0; // can happen during closing @@ -174,7 +179,7 @@ void WebChannelIPCTransport::installWebChannel(uint worldId) blink::WebView *webView = render_view()->GetWebView(); if (!webView) return; - WebChannelTransport::Install(webView->mainFrame(), worldId); + WebChannelTransport::Install(webView->MainFrame(), worldId); m_installed = true; m_installedWorldId = worldId; } @@ -185,7 +190,7 @@ void WebChannelIPCTransport::uninstallWebChannel(uint worldId) blink::WebView *webView = render_view()->GetWebView(); if (!webView) return; - WebChannelTransport::Uninstall(webView->mainFrame(), worldId); + WebChannelTransport::Uninstall(webView->MainFrame(), worldId); m_installed = false; } @@ -201,12 +206,12 @@ void WebChannelIPCTransport::dispatchWebChannelMessage(const std::vector<char> & v8::Isolate *isolate = v8::Isolate::GetCurrent(); v8::HandleScope handleScope(isolate); - blink::WebFrame *frame = webView->mainFrame(); + blink::WebFrame *frame = webView->MainFrame(); v8::Handle<v8::Context> context; if (worldId == 0) - context = frame->mainWorldScriptContext(); + context = frame->ToWebLocalFrame()->MainWorldScriptContext(); else - context = frame->toWebLocalFrame()->isolatedWorldScriptContext(worldId, 0); + context = frame->ToWebLocalFrame()->IsolatedWorldScriptContext(worldId); v8::Context::Scope contextScope(context); v8::Handle<v8::Object> global(context->Global()); @@ -234,7 +239,7 @@ void WebChannelIPCTransport::dispatchWebChannelMessage(const std::vector<char> & const int argc = 1; v8::Handle<v8::Value> argv[argc]; argv[0] = messageObject; - frame->callFunctionEvenIfScriptDisabled(callback, webChannelObjectValue->ToObject(), argc, argv); + frame->ToWebLocalFrame()->CallFunctionEvenIfScriptDisabled(callback, webChannelObjectValue->ToObject(), argc, argv); } bool WebChannelIPCTransport::OnMessageReceived(const IPC::Message &message) @@ -249,4 +254,9 @@ bool WebChannelIPCTransport::OnMessageReceived(const IPC::Message &message) return handled; } +void WebChannelIPCTransport::OnDestruct() +{ + delete this; +} + } // namespace diff --git a/src/core/renderer/web_channel_ipc_transport.h b/src/core/renderer/web_channel_ipc_transport.h index a2c7d5b4e..04041c6c7 100644 --- a/src/core/renderer/web_channel_ipc_transport.h +++ b/src/core/renderer/web_channel_ipc_transport.h @@ -71,7 +71,7 @@ private: // content::RenderViewObserver overrides: bool OnMessageReceived(const IPC::Message &message) override; - void OnDestruct() override { } + void OnDestruct() override; bool m_installed; uint m_installedWorldId; diff --git a/src/core/renderer_host/resource_dispatcher_host_delegate_qt.h b/src/core/renderer_host/resource_dispatcher_host_delegate_qt.h index e7701751e..305f0cea5 100644 --- a/src/core/renderer_host/resource_dispatcher_host_delegate_qt.h +++ b/src/core/renderer_host/resource_dispatcher_host_delegate_qt.h @@ -68,11 +68,6 @@ private: void triggerDialog(); void destroy(); - QUrl m_url; - QString m_realm; - bool m_isProxy; - QString m_host; - int m_renderProcessId; int m_renderFrameId; diff --git a/src/core/renderer_host/user_resource_controller_host.cpp b/src/core/renderer_host/user_resource_controller_host.cpp index cf0cbd357..2799d5d85 100644 --- a/src/core/renderer_host/user_resource_controller_host.cpp +++ b/src/core/renderer_host/user_resource_controller_host.cpp @@ -47,6 +47,7 @@ #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_process_host_observer.h" #include "content/public/browser/render_view_host.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" @@ -57,8 +58,9 @@ public: WebContentsObserverHelper(UserResourceControllerHost *, content::WebContents *); // WebContentsObserver overrides: - void RenderViewCreated(content::RenderViewHost *renderViewHost) override; - void RenderViewHostChanged(content::RenderViewHost *oldHost, content::RenderViewHost *newHost) override; + void RenderFrameCreated(content::RenderFrameHost *renderFrameHost) override; + void RenderFrameHostChanged(content::RenderFrameHost *oldHost, + content::RenderFrameHost *newHost) override; void WebContentsDestroyed() override; private: @@ -71,18 +73,21 @@ UserResourceControllerHost::WebContentsObserverHelper::WebContentsObserverHelper { } -void UserResourceControllerHost::WebContentsObserverHelper::RenderViewCreated(content::RenderViewHost *renderViewHost) +void UserResourceControllerHost::WebContentsObserverHelper::RenderFrameCreated( + content::RenderFrameHost *renderFrameHost) { content::WebContents *contents = web_contents(); Q_FOREACH (const UserScript &script, m_controllerHost->m_perContentsScripts.value(contents)) - renderViewHost->Send(new RenderViewObserverHelper_AddScript(renderViewHost->GetRoutingID(), script.data())); + renderFrameHost->Send(new RenderFrameObserverHelper_AddScript( + renderFrameHost->GetRoutingID(), script.data())); } -void UserResourceControllerHost::WebContentsObserverHelper::RenderViewHostChanged(content::RenderViewHost *oldHost, - content::RenderViewHost */*newHost*/) +void UserResourceControllerHost::WebContentsObserverHelper::RenderFrameHostChanged( + content::RenderFrameHost *oldHost, + content::RenderFrameHost *newHost) { if (oldHost) - oldHost->Send(new RenderViewObserverHelper_ClearScripts(oldHost->GetRoutingID())); + oldHost->Send(new RenderFrameObserverHelper_ClearScripts(oldHost->GetRoutingID())); } void UserResourceControllerHost::WebContentsObserverHelper::WebContentsDestroyed() @@ -115,7 +120,8 @@ void UserResourceControllerHost::addUserScript(const UserScript &script, WebCont if (script.isNull()) return; // Global scripts should be dispatched to all our render processes. - if (!adapter) { + const bool isProfileWideScript = !adapter; + if (isProfileWideScript) { if (!m_profileWideScripts.contains(script)) { m_profileWideScripts.append(script); Q_FOREACH (content::RenderProcessHost *renderer, m_observedProcesses) @@ -136,7 +142,9 @@ void UserResourceControllerHost::addUserScript(const UserScript &script, WebCont m_perContentsScripts.insert(contents, currentScripts); } } - contents->Send(new RenderViewObserverHelper_AddScript(contents->GetRoutingID(), script.data())); + contents->Send(new RenderFrameObserverHelper_AddScript(contents->GetRenderViewHost()-> + GetMainFrame()->GetRoutingID(), + script.data())); } } @@ -145,7 +153,8 @@ bool UserResourceControllerHost::containsUserScript(const UserScript &script, We if (script.isNull()) return false; // Global scripts should be dispatched to all our render processes. - if (!adapter) + const bool isProfileWideScript = !adapter; + if (isProfileWideScript) return m_profileWideScripts.contains(script); return m_perContentsScripts.value(adapter->webContents()).contains(script); } @@ -154,7 +163,8 @@ bool UserResourceControllerHost::removeUserScript(const UserScript &script, WebC { if (script.isNull()) return false; - if (!adapter) { + const bool isProfileWideScript = !adapter; + if (isProfileWideScript) { QList<UserScript>::iterator it = std::find(m_profileWideScripts.begin(), m_profileWideScripts.end(), script); if (it == m_profileWideScripts.end()) @@ -170,7 +180,9 @@ 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->Send(new RenderViewObserverHelper_RemoveScript(contents->GetRoutingID(), (*it).data())); + contents->Send(new RenderFrameObserverHelper_RemoveScript(contents-> + GetMainFrame()->GetRoutingID(), + (*it).data())); list.erase(it); } return true; @@ -178,27 +190,31 @@ bool UserResourceControllerHost::removeUserScript(const UserScript &script, WebC void UserResourceControllerHost::clearAllScripts(WebContentsAdapter *adapter) { - if (!adapter) { + const bool isProfileWideScript = !adapter; + if (isProfileWideScript) { m_profileWideScripts.clear(); Q_FOREACH (content::RenderProcessHost *renderer, m_observedProcesses) renderer->Send(new UserResourceController_ClearScripts); } else { content::WebContents *contents = adapter->webContents(); m_perContentsScripts.remove(contents); - contents->Send(new RenderViewObserverHelper_ClearScripts(contents->GetRoutingID())); + contents->Send(new RenderFrameObserverHelper_ClearScripts(contents-> + GetMainFrame()->GetRoutingID())); } } const QList<UserScript> UserResourceControllerHost::registeredScripts(WebContentsAdapter *adapter) const { - if (!adapter) + const bool isProfileWideScript = !adapter; + if (isProfileWideScript) return m_profileWideScripts; return m_perContentsScripts.value(adapter->webContents()); } void UserResourceControllerHost::reserve(WebContentsAdapter *adapter, int count) { - if (!adapter) + const bool isProfileWideScript = !adapter; + if (isProfileWideScript) m_profileWideScripts.reserve(count); else m_perContentsScripts[adapter->webContents()].reserve(count); 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 a093632bc..c47b255b7 100644 --- a/src/core/renderer_host/web_channel_ipc_transport_host.cpp +++ b/src/core/renderer_host/web_channel_ipc_transport_host.cpp @@ -93,6 +93,7 @@ void WebChannelIPCTransportHost::sendMessage(const QJsonObject &message) void WebChannelIPCTransportHost::onWebChannelMessage(const std::vector<char> &message) { + Q_ASSERT(!message.empty()); QJsonDocument doc = QJsonDocument::fromRawData(message.data(), message.size(), QJsonDocument::BypassValidation); Q_ASSERT(doc.isObject()); Q_EMIT messageReceived(doc.object(), this); diff --git a/src/core/resource_bundle_qt.cpp b/src/core/resource_bundle_qt.cpp index cc3c1de06..c37854ea6 100644 --- a/src/core/resource_bundle_qt.cpp +++ b/src/core/resource_bundle_qt.cpp @@ -38,7 +38,7 @@ ****************************************************************************/ #include "base/command_line.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "content/public/common/content_switches.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/data_pack.h" diff --git a/src/core/surface_factory_qt.cpp b/src/core/surface_factory_qt.cpp index 9b47d74a7..8c0bd6c82 100644 --- a/src/core/surface_factory_qt.cpp +++ b/src/core/surface_factory_qt.cpp @@ -44,7 +44,12 @@ #include "base/files/file_path.h" #include "base/native_library.h" +#include "ui/gl/gl_context_egl.h" #include "ui/gl/gl_implementation.h" +#include "ui/gl/gl_surface.h" +#include "ui/gl/init/gl_initializer.h" +#include "ui/gl/init/gl_factory.h" +#include "ui/ozone/common/gl_ozone_egl.h" #include <QGuiApplication> @@ -58,7 +63,37 @@ Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context(); namespace QtWebEngineCore { -bool SurfaceFactoryQt::LoadEGLGLES2Bindings() +class GLOzoneQt : public ui::GLOzoneEGL { +public: + scoped_refptr<gl::GLSurface> CreateViewGLSurface(gfx::AcceleratedWidget /*window*/) override + { + return nullptr; + } + scoped_refptr<gl::GLSurface> CreateOffscreenGLSurface(const gfx::Size& /*size*/) override + { + return nullptr; + } + +protected: + // Returns native platform display handle. This is used to obtain the EGL + // display connection for the native display. + intptr_t GetNativeDisplay() override; + + // Sets up GL bindings for the native surface. + bool LoadGLES2Bindings(gl::GLImplementation implementation) override; +}; + +base::NativeLibrary LoadLibrary(const base::FilePath& filename) { + base::NativeLibraryLoadError error; + base::NativeLibrary library = base::LoadNativeLibrary(filename, &error); + if (!library) { + LOG(ERROR) << "Failed to load " << filename.MaybeAsASCII() << ": " << error.ToString(); + return NULL; + } + return library; +} + +bool GLOzoneQt::LoadGLES2Bindings(gl::GLImplementation /*implementation*/) { base::NativeLibrary eglgles2Library = dlopen(NULL, RTLD_LAZY); if (!eglgles2Library) { @@ -89,7 +124,7 @@ bool SurfaceFactoryQt::LoadEGLGLES2Bindings() return true; } -intptr_t SurfaceFactoryQt::GetNativeDisplay() +intptr_t GLOzoneQt::GetNativeDisplay() { static void *display = GLContextHelper::getNativeDisplay(); @@ -99,6 +134,18 @@ intptr_t SurfaceFactoryQt::GetNativeDisplay() return reinterpret_cast<intptr_t>(EGL_DEFAULT_DISPLAY); } +std::vector<gl::GLImplementation> SurfaceFactoryQt::GetAllowedGLImplementations() +{ + std::vector<gl::GLImplementation> impls; + impls.push_back(gl::kGLImplementationEGLGLES2); + return impls; +} + +ui::GLOzone* SurfaceFactoryQt::GetGLOzone(gl::GLImplementation implementation) +{ + return new GLOzoneQt(); +} + } // namespace QtWebEngineCore #endif // defined(USE_OZONE) diff --git a/src/core/surface_factory_qt.h b/src/core/surface_factory_qt.h index 76b6dc6ed..b7991829c 100644 --- a/src/core/surface_factory_qt.h +++ b/src/core/surface_factory_qt.h @@ -46,11 +46,10 @@ namespace QtWebEngineCore { -class SurfaceFactoryQt - : public ui::SurfaceFactoryOzone +class SurfaceFactoryQt : public ui::SurfaceFactoryOzone { - bool LoadEGLGLES2Bindings() override; - intptr_t GetNativeDisplay() override; + std::vector<gl::GLImplementation> GetAllowedGLImplementations() override; + ui::GLOzone* GetGLOzone(gl::GLImplementation implementation) override; }; } // namespace QtWebEngineCore diff --git a/src/core/type_conversion.cpp b/src/core/type_conversion.cpp index a7b5ee831..685ee273e 100644 --- a/src/core/type_conversion.cpp +++ b/src/core/type_conversion.cpp @@ -39,6 +39,7 @@ #include "type_conversion.h" +#include <content/public/common/favicon_url.h> #include <ui/events/event_constants.h> #include <ui/gfx/image/image_skia.h> #include <QtCore/qcoreapplication.h> @@ -104,17 +105,6 @@ QImage toQImage(const SkBitmap &bitmap) break; } break; - case kIndex_8_SkColorType: { - image = toQImage(bitmap, QImage::Format_Indexed8); - SkColorTable *skTable = bitmap.getColorTable(); - if (skTable) { - QVector<QRgb> qTable(skTable->count()); - for (int i = 0; i < skTable->count(); ++i) - qTable[i] = (*skTable)[i]; - image.setColorTable(qTable); - } - break; - } case kGray_8_SkColorType: image = toQImage(bitmap, QImage::Format_Grayscale8); break; @@ -171,31 +161,30 @@ int flagsFromModifiers(Qt::KeyboardModifiers modifiers) return modifierFlags; } +FaviconInfo::FaviconType toQt(content::FaviconURL::IconType type) +{ + switch (type) { + case content::FaviconURL::IconType::kFavicon: + return FaviconInfo::Favicon; + case content::FaviconURL::IconType::kTouchIcon: + return FaviconInfo::TouchIcon; + case content::FaviconURL::IconType::kTouchPrecomposedIcon: + return FaviconInfo::TouchPrecomposedIcon; + case content::FaviconURL::IconType::kInvalid: + return FaviconInfo::InvalidIcon; + } + Q_UNREACHABLE(); + return FaviconInfo::InvalidIcon; +} + FaviconInfo toFaviconInfo(const content::FaviconURL &favicon_url) { FaviconInfo info; - info.url = toQt(favicon_url.icon_url); - - switch (favicon_url.icon_type) { - case content::FaviconURL::FAVICON: - info.type = FaviconInfo::Favicon; - break; - case content::FaviconURL::TOUCH_ICON: - info.type = FaviconInfo::TouchIcon; - break; - case content::FaviconURL::TOUCH_PRECOMPOSED_ICON: - info.type = FaviconInfo::TouchPrecomposedIcon; - break; - default: - info.type = FaviconInfo::InvalidIcon; - break; - } - + 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); - return info; } diff --git a/src/core/type_conversion.h b/src/core/type_conversion.h index 39c4f610c..eb7c9d48b 100644 --- a/src/core/type_conversion.h +++ b/src/core/type_conversion.h @@ -54,7 +54,6 @@ #include "base/files/file_path.h" #include "base/time/time.h" #include "content/public/common/file_chooser_file_info.h" -#include "content/public/common/favicon_url.h" #include "favicon_manager.h" #include "net/cookies/canonical_cookie.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -65,6 +64,10 @@ #include "ui/gfx/geometry/rect_f.h" #include "url/gurl.h" +namespace content { +struct FaviconURL; +} + namespace gfx { class ImageSkiaRep; } diff --git a/src/core/url_request_context_getter_qt.cpp b/src/core/url_request_context_getter_qt.cpp index 1f3d6fcbe..10a6cfe7a 100644 --- a/src/core/url_request_context_getter_qt.cpp +++ b/src/core/url_request_context_getter_qt.cpp @@ -54,11 +54,12 @@ #include "net/cert/ct_log_verifier.h" #include "net/cert/ct_policy_enforcer.h" #include "net/cert/multi_log_ct_verifier.h" -#include "net/disk_cache/disk_cache.h" #include "net/dns/host_resolver.h" #include "net/dns/mapped_host_resolver.h" #include "net/extras/sqlite/sqlite_channel_id_store.h" #include "net/http/http_auth_handler_factory.h" +#include "net/http/http_auth_preferences.h" +#include "net/http/http_auth_scheme.h" #include "net/http/http_cache.h" #include "net/http/http_network_session.h" #include "net/http/http_server_properties_impl.h" @@ -175,9 +176,7 @@ void URLRequestContextGetterQt::updateStorageSettings() m_proxyConfigService = new ProxyConfigServiceQt( net::ProxyService::CreateSystemProxyConfigService( - content::BrowserThread::GetTaskRunnerForThread(BrowserThread::IO), - content::BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE) - )); + content::BrowserThread::GetTaskRunnerForThread(BrowserThread::IO))); if (m_contextInitialized) content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestContextGetterQt::generateAllStorage, this)); @@ -189,9 +188,9 @@ void URLRequestContextGetterQt::cancelAllUrlRequests() Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); Q_ASSERT(m_urlRequestContext); - std::set<const net::URLRequest*>* url_requests = m_urlRequestContext->url_requests(); - std::set<const net::URLRequest*>::const_iterator it = url_requests->begin(); - std::set<const net::URLRequest*>::const_iterator end = url_requests->end(); + 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) @@ -211,6 +210,13 @@ void URLRequestContextGetterQt::generateAllStorage() m_updateAllStorage = false; } +static const char* const kDefaultAuthSchemes[] = { net::kBasicAuthScheme, + net::kDigestAuthScheme, +#if defined(USE_KERBEROS) && !defined(OS_ANDROID) + net::kNegotiateAuthScheme, +#endif + net::kNtlmAuthScheme }; + void URLRequestContextGetterQt::generateStorage() { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); @@ -253,7 +259,15 @@ void URLRequestContextGetterQt::generateStorage() m_storage->set_ssl_config_service(new net::SSLConfigServiceDefaults); m_storage->set_transport_security_state(std::unique_ptr<net::TransportSecurityState>(new net::TransportSecurityState())); - m_storage->set_http_auth_handler_factory(net::HttpAuthHandlerFactory::CreateDefault(host_resolver.get())); + if (!m_httpAuthPreferences) { + std::vector<std::string> auth_types(std::begin(kDefaultAuthSchemes), std::end(kDefaultAuthSchemes)); + m_httpAuthPreferences.reset(new net::HttpAuthPreferences(auth_types +#if defined(OS_POSIX) && !defined(OS_ANDROID) + , std::string() /* gssapi library name */ +#endif + )); + } + m_storage->set_http_auth_handler_factory(net::HttpAuthHandlerRegistryFactory::Create(m_httpAuthPreferences.get(), host_resolver.get())); m_storage->set_http_server_properties(std::unique_ptr<net::HttpServerProperties>(new net::HttpServerPropertiesImpl)); // Give |m_storage| ownership at the end in case it's |mapped_host_resolver|. @@ -295,8 +309,7 @@ void URLRequestContextGetterQt::generateCookieStore() m_storage->set_channel_id_service( base::WrapUnique(new net::ChannelIDService( - new net::DefaultChannelIDStore(channel_id_db.get()), - base::WorkerPool::GetTaskRunner(true)))); + new net::DefaultChannelIDStore(channel_id_db.get())))); // Unset it first to get a chance to destroy and flush the old cookie store before opening a new on possibly the same file. m_storage->set_cookie_store(0); @@ -411,7 +424,7 @@ void URLRequestContextGetterQt::updateRequestInterceptor() // We in this case do not need to regenerate any Chromium classes. } -static bool doNetworkSessionParamsMatch(const net::HttpNetworkSession::Params &first, const net::HttpNetworkSession::Params &second) +static bool doNetworkSessionContextMatch(const net::HttpNetworkSession::Context &first, const net::HttpNetworkSession::Context &second) { if (first.transport_security_state != second.transport_security_state) return false; @@ -427,8 +440,6 @@ static bool doNetworkSessionParamsMatch(const net::HttpNetworkSession::Params &f return false; if (first.http_server_properties != second.http_server_properties) return false; - if (first.ignore_certificate_errors != second.ignore_certificate_errors) - return false; if (first.host_resolver != second.host_resolver) return false; if (first.cert_transparency_verifier != second.cert_transparency_verifier) @@ -439,23 +450,41 @@ static bool doNetworkSessionParamsMatch(const net::HttpNetworkSession::Params &f return true; } +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; +} + +net::HttpNetworkSession::Context URLRequestContextGetterQt::generateNetworkSessionContext() +{ + Q_ASSERT(m_urlRequestContext); + + net::HttpNetworkSession::Context network_session_context; + + network_session_context.transport_security_state = m_urlRequestContext->transport_security_state(); + network_session_context.cert_verifier = m_urlRequestContext->cert_verifier(); + network_session_context.channel_id_service = m_urlRequestContext->channel_id_service(); + network_session_context.proxy_service = m_urlRequestContext->proxy_service(); + network_session_context.ssl_config_service = m_urlRequestContext->ssl_config_service(); + network_session_context.http_auth_handler_factory = m_urlRequestContext->http_auth_handler_factory(); + network_session_context.http_server_properties = m_urlRequestContext->http_server_properties(); + network_session_context.host_resolver = m_urlRequestContext->host_resolver(); + network_session_context.cert_transparency_verifier = m_urlRequestContext->cert_transparency_verifier(); + network_session_context.ct_policy_enforcer = m_urlRequestContext->ct_policy_enforcer(); + + return network_session_context; +} + net::HttpNetworkSession::Params URLRequestContextGetterQt::generateNetworkSessionParams() { Q_ASSERT(m_urlRequestContext); net::HttpNetworkSession::Params network_session_params; - network_session_params.transport_security_state = m_urlRequestContext->transport_security_state(); - network_session_params.cert_verifier = m_urlRequestContext->cert_verifier(); - network_session_params.channel_id_service = m_urlRequestContext->channel_id_service(); - network_session_params.proxy_service = m_urlRequestContext->proxy_service(); - network_session_params.ssl_config_service = m_urlRequestContext->ssl_config_service(); - network_session_params.http_auth_handler_factory = m_urlRequestContext->http_auth_handler_factory(); - network_session_params.http_server_properties = m_urlRequestContext->http_server_properties(); network_session_params.ignore_certificate_errors = m_ignoreCertificateErrors; - network_session_params.host_resolver = m_urlRequestContext->host_resolver(); - network_session_params.cert_transparency_verifier = m_urlRequestContext->cert_transparency_verifier(); - network_session_params.ct_policy_enforcer = m_urlRequestContext->ct_policy_enforcer(); return network_session_params; } @@ -500,11 +529,14 @@ void URLRequestContextGetterQt::generateHttpCache() } net::HttpCache *cache = 0; + net::HttpNetworkSession::Context network_session_context = generateNetworkSessionContext(); net::HttpNetworkSession::Params network_session_params = generateNetworkSessionParams(); - if (!m_httpNetworkSession || !doNetworkSessionParamsMatch(network_session_params, m_httpNetworkSession->params())) { + if (!m_httpNetworkSession + || !doNetworkSessionParamsMatch(network_session_params, m_httpNetworkSession->params()) + || !doNetworkSessionContextMatch(network_session_context, m_httpNetworkSession->context())) { cancelAllUrlRequests(); - m_httpNetworkSession.reset(new net::HttpNetworkSession(network_session_params)); + 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); @@ -512,23 +544,6 @@ void URLRequestContextGetterQt::generateHttpCache() m_storage->set_http_transaction_factory(std::unique_ptr<net::HttpCache>(cache)); } -void URLRequestContextGetterQt::clearHttpCache() -{ - if (m_urlRequestContext) - content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestContextGetterQt::clearCurrentCacheBackend, this)); -} - -static void doomCallback(int error_code) { Q_UNUSED(error_code); } - -void URLRequestContextGetterQt::clearCurrentCacheBackend() -{ - if (m_urlRequestContext->http_transaction_factory() && m_urlRequestContext->http_transaction_factory()->GetCache()) { - disk_cache::Backend *backend = m_urlRequestContext->http_transaction_factory()->GetCache()->GetCurrentBackend(); - if (backend) - backend->DoomAllEntries(base::Bind(&doomCallback)); - } -} - void URLRequestContextGetterQt::generateJobFactory() { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); @@ -572,10 +587,11 @@ void URLRequestContextGetterQt::generateJobFactory() // Set up interceptors in the reverse order. std::unique_ptr<net::URLRequestJobFactory> topJobFactory = std::move(jobFactory); - for (content::URLRequestInterceptorScopedVector::reverse_iterator i = m_requestInterceptors.rbegin(); i != m_requestInterceptors.rend(); ++i) - topJobFactory.reset(new net::URLRequestInterceptingJobFactory(std::move(topJobFactory), std::unique_ptr<net::URLRequestInterceptor>(*i))); + for (content::URLRequestInterceptorScopedVector::reverse_iterator i = m_requestInterceptors.rbegin(); i != m_requestInterceptors.rend(); ++i) { + topJobFactory.reset(new net::URLRequestInterceptingJobFactory(std::move(topJobFactory), std::move(*i))); + } - m_requestInterceptors.weak_clear(); + m_requestInterceptors.clear(); m_jobFactory = std::move(topJobFactory); diff --git a/src/core/url_request_context_getter_qt.h b/src/core/url_request_context_getter_qt.h index 9757cc73e..4a97a1398 100644 --- a/src/core/url_request_context_getter_qt.h +++ b/src/core/url_request_context_getter_qt.h @@ -62,6 +62,7 @@ #include <QtCore/qsharedpointer.h> namespace net { +class HttpAuthPreferences; class MappedHostResolver; class ProxyConfigService; } @@ -81,7 +82,6 @@ public: void updateUserAgent(); void updateCookieStore(); void updateHttpCache(); - void clearHttpCache(); void updateJobFactory(); void updateRequestInterceptor(); @@ -96,9 +96,9 @@ private: void generateUserAgent(); void generateJobFactory(); void regenerateJobFactory(); - void clearCurrentCacheBackend(); void cancelAllUrlRequests(); net::HttpNetworkSession::Params generateNetworkSessionParams(); + net::HttpNetworkSession::Context generateNetworkSessionContext(); void setFullConfiguration(QSharedPointer<BrowserContextAdapter> browserContext); @@ -125,6 +125,7 @@ private: scoped_refptr<CookieMonsterDelegateQt> m_cookieDelegate; content::URLRequestInterceptorScopedVector m_requestInterceptors; std::unique_ptr<net::HttpNetworkSession> m_httpNetworkSession; + std::unique_ptr<net::HttpAuthPreferences> m_httpAuthPreferences; QList<QByteArray> m_installedCustomSchemes; QWebEngineUrlRequestInterceptor* m_requestInterceptor; diff --git a/src/core/url_request_custom_job.cpp b/src/core/url_request_custom_job.cpp index d093efd0a..070414b4b 100644 --- a/src/core/url_request_custom_job.cpp +++ b/src/core/url_request_custom_job.cpp @@ -38,69 +38,72 @@ ****************************************************************************/ #include "url_request_custom_job.h" -#include "url_request_custom_job_delegate.h" - -#include "api/qwebengineurlrequestjob.h" -#include "api/qwebengineurlschemehandler.h" -#include "browser_context_adapter.h" -#include "type_conversion.h" - +#include "url_request_custom_job_proxy.h" #include "content/public/browser/browser_thread.h" -#include "net/base/net_errors.h" #include "net/base/io_buffer.h" -#include <QFileInfo> -#include <QMimeDatabase> -#include <QMimeType> -#include <QUrl> +#include <QIODevice> using namespace net; namespace QtWebEngineCore { -URLRequestCustomJob::URLRequestCustomJob(URLRequest *request, NetworkDelegate *networkDelegate, - const std::string &scheme, QWeakPointer<const BrowserContextAdapter> adapter) +URLRequestCustomJob::URLRequestCustomJob(URLRequest *request, + NetworkDelegate *networkDelegate, + const std::string &scheme, + QWeakPointer<const BrowserContextAdapter> adapter) : URLRequestJob(request, networkDelegate) - , m_scheme(scheme) - , m_adapter(adapter) - , m_shared(new URLRequestCustomJobShared(this)) + , m_proxy(new URLRequestCustomJobProxy(this, scheme, adapter)) + , m_device(nullptr) + , m_error(0) + , m_pendingReadSize(0) + , m_pendingReadPos(0) + , m_pendingReadBuffer(nullptr) { } URLRequestCustomJob::~URLRequestCustomJob() { - if (m_shared) - m_shared->killJob(); -} - -static void startAsync(URLRequestCustomJobShared *shared) -{ - shared->startAsync(); + m_proxy->m_job = nullptr; + if (m_device && m_device->isOpen()) + m_device->close(); + m_device = nullptr; + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, + base::Bind(&URLRequestCustomJobProxy::release, + m_proxy)); } void URLRequestCustomJob::Start() { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, base::Bind(&startAsync, m_shared)); + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, + base::Bind(&URLRequestCustomJobProxy::initialize, + m_proxy, request()->url(), request()->method())); } void URLRequestCustomJob::Kill() { - if (m_shared) - m_shared->killJob(); - m_shared = 0; - + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + 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; + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, + base::Bind(&URLRequestCustomJobProxy::release, + m_proxy)); URLRequestJob::Kill(); } bool URLRequestCustomJob::GetMimeType(std::string *mimeType) const { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (!m_shared) - return false; - QMutexLocker lock(&m_shared->m_mutex); - if (m_shared->m_mimeType.size() > 0) { - *mimeType = m_shared->m_mimeType; + if (m_mimeType.size() > 0) { + *mimeType = m_mimeType; return true; } return false; @@ -109,11 +112,8 @@ bool URLRequestCustomJob::GetMimeType(std::string *mimeType) const bool URLRequestCustomJob::GetCharset(std::string* charset) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (!m_shared) - return false; - QMutexLocker lock(&m_shared->m_mutex); - if (m_shared->m_charset.size() > 0) { - *charset = m_shared->m_charset; + if (m_charset.size() > 0) { + *charset = m_charset; return true; } return false; @@ -122,11 +122,8 @@ bool URLRequestCustomJob::GetCharset(std::string* charset) bool URLRequestCustomJob::IsRedirectResponse(GURL* location, int* http_status_code) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (!m_shared) - return false; - QMutexLocker lock(&m_shared->m_mutex); - if (m_shared->m_redirect.is_valid()) { - *location = m_shared->m_redirect; + if (m_redirect.is_valid()) { + *location = m_redirect; *http_status_code = 303; return true; } @@ -136,224 +133,67 @@ bool URLRequestCustomJob::IsRedirectResponse(GURL* location, int* http_status_co int URLRequestCustomJob::ReadRawData(IOBuffer *buf, int bufSize) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - Q_ASSERT(m_shared); - QMutexLocker lock(&m_shared->m_mutex); - if (m_shared->m_error) - return m_shared->m_error; - qint64 rv = m_shared->m_device ? m_shared->m_device->read(buf->data(), bufSize) : -1; - if (rv >= 0) + 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 { + } 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_shared->m_error) - return m_shared->m_error; + if (m_error) + return m_error; + if (m_device && m_device->atEnd()) + return 0; return ERR_FAILED; } } - -URLRequestCustomJobShared::URLRequestCustomJobShared(URLRequestCustomJob *job) - : m_mutex(QMutex::Recursive) - , m_job(job) - , m_delegate(0) - , m_error(0) - , m_started(false) - , m_asyncInitialized(false) - , m_weakFactory(this) -{ -} - -URLRequestCustomJobShared::~URLRequestCustomJobShared() -{ - Q_ASSERT(!m_job); - Q_ASSERT(!m_delegate); -} - -void URLRequestCustomJobShared::killJob() +void URLRequestCustomJob::notifyReadyRead() { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - QMutexLocker lock(&m_mutex); - m_job = 0; - bool doDelete = false; - if (m_delegate) { - m_delegate->deleteLater(); - } else { - // Do not delete yet if startAsync has not yet run. - doDelete = m_asyncInitialized; - } - if (m_device && m_device->isOpen()) - m_device->close(); - m_device = 0; - m_weakFactory.InvalidateWeakPtrs(); - lock.unlock(); - if (doDelete) - delete this; -} - -void URLRequestCustomJobShared::unsetJobDelegate() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - QMutexLocker lock(&m_mutex); - m_delegate = 0; - bool doDelete = false; - if (m_job) - abort(); - else - doDelete = true; - lock.unlock(); - if (doDelete) - delete this; -} - -void URLRequestCustomJobShared::setReplyMimeType(const std::string &mimeType) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - QMutexLocker lock(&m_mutex); - m_mimeType = mimeType; -} - -void URLRequestCustomJobShared::setReplyCharset(const std::string &charset) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - QMutexLocker lock(&m_mutex); - m_charset = charset; -} - -void URLRequestCustomJobShared::setReplyDevice(QIODevice *device) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - QMutexLocker lock(&m_mutex); - if (!m_job) + if (!m_device) return; - m_device = device; - if (m_device && !m_device->isReadable()) - m_device->open(QIODevice::ReadOnly); - - qint64 size = m_device ? m_device->size() : -1; - if (size > 0) - m_job->set_expected_content_size(size); - if (m_device && m_device->isReadable()) - content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestCustomJobShared::notifyStarted, m_weakFactory.GetWeakPtr())); - else - fail(ERR_INVALID_URL); -} - -void URLRequestCustomJobShared::redirect(const GURL &url) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - QMutexLocker lock(&m_mutex); - if (m_device || m_error) - return; - if (!m_job) - return; - m_redirect = url; - content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestCustomJobShared::notifyStarted, m_weakFactory.GetWeakPtr())); -} - -void URLRequestCustomJobShared::abort() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - QMutexLocker lock(&m_mutex); - if (m_device && m_device->isOpen()) - m_device->close(); - m_device = 0; - if (!m_job) - return; - content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestCustomJobShared::notifyCanceled, m_weakFactory.GetWeakPtr())); -} - -void URLRequestCustomJobShared::notifyCanceled() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - QMutexLocker lock(&m_mutex); - if (!m_job) - return; - if (m_started) - m_job->NotifyCanceled(); - else - m_job->NotifyStartError(URLRequestStatus(URLRequestStatus::CANCELED, ERR_ABORTED)); -} - -void URLRequestCustomJobShared::notifyStarted() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - QMutexLocker lock(&m_mutex); - if (!m_job) - return; - Q_ASSERT(!m_started); - m_started = true; - m_job->NotifyHeadersComplete(); -} - -void URLRequestCustomJobShared::fail(int error) -{ - QMutexLocker lock(&m_mutex); - m_error = error; - if (content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)) + if (!m_pendingReadSize) return; - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - if (!m_job) - return; - content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestCustomJobShared::notifyFailure, m_weakFactory.GetWeakPtr())); -} - -void URLRequestCustomJobShared::notifyFailure() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - QMutexLocker lock(&m_mutex); - if (!m_job) + Q_ASSERT(m_pendingReadBuffer); + if (!m_pendingReadBuffer) return; - if (m_device) - m_device->close(); - if (!m_started) - m_job->NotifyStartError(URLRequestStatus::FromError(m_error)); - // else we fail on the next read, or the read that might already be in progress -} -GURL URLRequestCustomJobShared::requestUrl() -{ - QMutexLocker lock(&m_mutex); - if (!m_job) - return GURL(); - return m_job->request()->url(); -} - -std::string URLRequestCustomJobShared::requestMethod() -{ - QMutexLocker lock(&m_mutex); - if (!m_job) - return std::string(); - return m_job->request()->method(); -} - -void URLRequestCustomJobShared::startAsync() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - Q_ASSERT(!m_started); - Q_ASSERT(!m_delegate); - QMutexLocker lock(&m_mutex); - if (!m_job) { - lock.unlock(); - delete this; + qint64 rv = m_device->read(m_pendingReadBuffer->data() + m_pendingReadPos, m_pendingReadSize - m_pendingReadPos); + if (rv == 0) return; - } - - QWebEngineUrlSchemeHandler *schemeHandler = 0; - QSharedPointer<const BrowserContextAdapter> browserContext = m_job->m_adapter.toStrongRef(); - if (browserContext) - schemeHandler = browserContext->customUrlSchemeHandlers()[toQByteArray(m_job->m_scheme)]; - if (schemeHandler) { - m_delegate = new URLRequestCustomJobDelegate(this); - m_asyncInitialized = true; - QWebEngineUrlRequestJob *requestJob = new QWebEngineUrlRequestJob(m_delegate); - schemeHandler->requestStarted(requestJob); + if (rv < 0) { + if (m_error) + rv = m_error; + else if (m_device->atEnd()) + rv = 0; + else + rv = ERR_FAILED; } else { - lock.unlock(); - abort(); - delete this; - return; + 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(); } } // namespace diff --git a/src/core/url_request_custom_job.h b/src/core/url_request_custom_job.h index 93edb0b8c..021cf3204 100644 --- a/src/core/url_request_custom_job.h +++ b/src/core/url_request_custom_job.h @@ -40,11 +40,9 @@ #ifndef URL_REQUEST_CUSTOM_JOB_H_ #define URL_REQUEST_CUSTOM_JOB_H_ -#include "net/url_request/url_request.h" #include "net/url_request/url_request_job.h" - -#include <QtCore/QMutex> -#include <QtCore/QPointer> +#include "url/gurl.h" +#include <QtCore/QWeakPointer> QT_FORWARD_DECLARE_CLASS(QIODevice) @@ -52,12 +50,15 @@ namespace QtWebEngineCore { class BrowserContextAdapter; class URLRequestCustomJobDelegate; -class URLRequestCustomJobShared; +class URLRequestCustomJobProxy; // A request job that handles reading custom URL schemes class URLRequestCustomJob : public net::URLRequestJob { public: - URLRequestCustomJob(net::URLRequest *request, net::NetworkDelegate *networkDelegate, const std::string &scheme, QWeakPointer<const BrowserContextAdapter> adapter); + URLRequestCustomJob(net::URLRequest *request, + net::NetworkDelegate *networkDelegate, + const std::string &scheme, + QWeakPointer<const BrowserContextAdapter> adapter); void Start() override; void Kill() override; int ReadRawData(net::IOBuffer *buf, int buf_size) override; @@ -69,54 +70,21 @@ protected: virtual ~URLRequestCustomJob(); private: - std::string m_scheme; - QWeakPointer<const BrowserContextAdapter> m_adapter; - URLRequestCustomJobShared *m_shared; - - friend class URLRequestCustomJobShared; - - DISALLOW_COPY_AND_ASSIGN(URLRequestCustomJob); -}; - -// A shared state between URLRequestCustomJob living on the IO thread -// and URLRequestCustomJobDelegate living on the UI thread. -class URLRequestCustomJobShared { -public: - URLRequestCustomJobShared(URLRequestCustomJob *job); - ~URLRequestCustomJobShared(); - - void setReplyMimeType(const std::string &); - void setReplyCharset(const std::string &); - void setReplyDevice(QIODevice *); - - void redirect(const GURL &url); - void fail(int); - void abort(); - - void killJob(); - void unsetJobDelegate(); - - void startAsync(); - void notifyStarted(); - void notifyFailure(); - void notifyCanceled(); - - GURL requestUrl(); - std::string requestMethod(); - - QMutex m_mutex; - QPointer<QIODevice> m_device; - URLRequestCustomJob *m_job; - URLRequestCustomJobDelegate *m_delegate; + void notifyReadyRead(); + scoped_refptr<URLRequestCustomJobProxy> m_proxy; std::string m_mimeType; std::string m_charset; - int m_error; GURL m_redirect; - bool m_started; - bool m_asyncInitialized; - base::WeakPtrFactory<URLRequestCustomJobShared> m_weakFactory; -}; + QIODevice *m_device; + int m_error; + int m_pendingReadSize; + int m_pendingReadPos; + net::IOBuffer *m_pendingReadBuffer; + + friend class URLRequestCustomJobProxy; + DISALLOW_COPY_AND_ASSIGN(URLRequestCustomJob); +}; } // namespace QtWebEngineCore #endif // URL_REQUEST_CUSTOM_JOB_H_ diff --git a/src/core/url_request_custom_job_delegate.cpp b/src/core/url_request_custom_job_delegate.cpp index 7e806a4e0..6b82cebb5 100644 --- a/src/core/url_request_custom_job_delegate.cpp +++ b/src/core/url_request_custom_job_delegate.cpp @@ -37,50 +37,66 @@ ** ****************************************************************************/ -#include "url_request_custom_job.h" #include "url_request_custom_job_delegate.h" +#include "url_request_custom_job_proxy.h" #include "type_conversion.h" #include "net/base/net_errors.h" +#include "content/public/browser/browser_thread.h" #include <QByteArray> namespace QtWebEngineCore { -URLRequestCustomJobDelegate::URLRequestCustomJobDelegate(URLRequestCustomJobShared *shared) - : m_shared(shared) +URLRequestCustomJobDelegate::URLRequestCustomJobDelegate(URLRequestCustomJobProxy *proxy, + const QUrl &url, + const QByteArray &method) + : m_proxy(proxy), + m_request(url), + m_method(method) { } URLRequestCustomJobDelegate::~URLRequestCustomJobDelegate() { - m_shared->unsetJobDelegate(); } QUrl URLRequestCustomJobDelegate::url() const { - return toQt(m_shared->requestUrl()); + return m_request; } QByteArray URLRequestCustomJobDelegate::method() const { - return QByteArray::fromStdString(m_shared->requestMethod()); + return m_method; } -void URLRequestCustomJobDelegate::setReply(const QByteArray &contentType, QIODevice *device) +void URLRequestCustomJobDelegate::reply(const QByteArray &contentType, QIODevice *device) { - m_shared->setReplyMimeType(contentType.toStdString()); - m_shared->setReplyDevice(device); + if (device) + QObject::connect(device, &QIODevice::readyRead, this, &URLRequestCustomJobDelegate::slotReadyRead); + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::Bind(&URLRequestCustomJobProxy::reply, + m_proxy,contentType.toStdString(),device)); +} + +void URLRequestCustomJobDelegate::slotReadyRead() +{ + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::Bind(&URLRequestCustomJobProxy::readyRead, m_proxy)); } void URLRequestCustomJobDelegate::abort() { - m_shared->abort(); + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::Bind(&URLRequestCustomJobProxy::abort, m_proxy)); } void URLRequestCustomJobDelegate::redirect(const QUrl &url) { - m_shared->redirect(toGurl(url)); + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::Bind(&URLRequestCustomJobProxy::redirect, + m_proxy, toGurl(url))); } void URLRequestCustomJobDelegate::fail(Error error) @@ -105,8 +121,11 @@ void URLRequestCustomJobDelegate::fail(Error error) net_error = net::ERR_FAILED; break; } - if (net_error) - m_shared->fail(net_error); + if (net_error) { + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::Bind(&URLRequestCustomJobProxy::fail, + m_proxy, net_error)); + } } } // namespace diff --git a/src/core/url_request_custom_job_delegate.h b/src/core/url_request_custom_job_delegate.h index 7752d979e..3f5e6d591 100644 --- a/src/core/url_request_custom_job_delegate.h +++ b/src/core/url_request_custom_job_delegate.h @@ -40,6 +40,7 @@ #ifndef URL_REQUEST_CUSTOM_JOB_DELEGATE_H_ #define URL_REQUEST_CUSTOM_JOB_DELEGATE_H_ +#include "base/memory/ref_counted.h" #include "qtwebenginecoreglobal.h" #include <QObject> @@ -49,7 +50,7 @@ QT_FORWARD_DECLARE_CLASS(QIODevice) namespace QtWebEngineCore { -class URLRequestCustomJobShared; +class URLRequestCustomJobProxy; class QWEBENGINE_EXPORT URLRequestCustomJobDelegate : public QObject { Q_OBJECT @@ -68,17 +69,23 @@ public: QUrl url() const; QByteArray method() const; - void setReply(const QByteArray &contentType, QIODevice *device); + void reply(const QByteArray &contentType, QIODevice *device); void redirect(const QUrl& url); void abort(); - void fail(Error); +private Q_SLOTS: + void slotReadyRead(); + private: - URLRequestCustomJobDelegate(URLRequestCustomJobShared *shared); + URLRequestCustomJobDelegate(URLRequestCustomJobProxy *proxy, + const QUrl &url, + const QByteArray &method); - friend class URLRequestCustomJobShared; - URLRequestCustomJobShared *m_shared; + friend class URLRequestCustomJobProxy; + scoped_refptr<URLRequestCustomJobProxy> m_proxy; + QUrl m_request; + QByteArray m_method; }; } // namespace diff --git a/src/core/url_request_custom_job_proxy.cpp b/src/core/url_request_custom_job_proxy.cpp new file mode 100644 index 000000000..832d3d11e --- /dev/null +++ b/src/core/url_request_custom_job_proxy.cpp @@ -0,0 +1,171 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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_proxy.h" +#include "url_request_custom_job.h" +#include "url_request_custom_job_delegate.h" +#include "api/qwebengineurlrequestjob.h" +#include "browser_context_adapter.h" +#include "type_conversion.h" +#include "content/public/browser/browser_thread.h" + +using namespace net; + +namespace QtWebEngineCore { + +URLRequestCustomJobProxy::URLRequestCustomJobProxy(URLRequestCustomJob *job, + const std::string &scheme, + QWeakPointer<const BrowserContextAdapter> adapter) + : m_job(job) + , m_started(false) + , m_scheme(scheme) + , m_delegate(nullptr) + , m_adapter(adapter) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); +} + +URLRequestCustomJobProxy::~URLRequestCustomJobProxy() +{ +} + +void URLRequestCustomJobProxy::release() +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (m_delegate) { + m_delegate->deleteLater(); + m_delegate = nullptr; + } +} + +// Fix me: this is never used +/* +void URLRequestCustomJobProxy::setReplyCharset(const std::string &charset) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (!m_job) + return; + m_job->m_charset = charset; +} +*/ +void URLRequestCustomJobProxy::reply(std::string mimeType, QIODevice *device) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (!m_job) + return; + m_job->m_mimeType = mimeType; + m_job->m_device = device; + if (m_job->m_device && !m_job->m_device->isReadable()) + m_job->m_device->open(QIODevice::ReadOnly); + + qint64 size = m_job->m_device ? m_job->m_device->size() : -1; + if (size > 0) + m_job->set_expected_content_size(size); + if (m_job->m_device && m_job->m_device->isReadable()) { + m_started = true; + m_job->NotifyHeadersComplete(); + } else { + fail(ERR_INVALID_URL); + } +} + +void URLRequestCustomJobProxy::redirect(GURL url) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (!m_job) + return; + if (m_job->m_device || m_job->m_error) + return; + m_job->m_redirect = url; + m_started = true; + m_job->NotifyHeadersComplete(); +} + +void URLRequestCustomJobProxy::abort() +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (!m_job) + return; + if (m_job->m_device && m_job->m_device->isOpen()) + m_job->m_device->close(); + m_job->m_device = nullptr; + if (m_started) + m_job->NotifyCanceled(); + else + m_job->NotifyStartError(URLRequestStatus(URLRequestStatus::CANCELED, ERR_ABORTED)); +} + +void URLRequestCustomJobProxy::fail(int error) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (!m_job) + return; + m_job->m_error = error; + if (m_job->m_device) + m_job->m_device->close(); + if (!m_started) + m_job->NotifyStartError(URLRequestStatus::FromError(error)); + // else we fail on the next read, or the read that might already be in progress +} + +void URLRequestCustomJobProxy::readyRead() +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (m_job) + m_job->notifyReadyRead(); +} + +void URLRequestCustomJobProxy::initialize(GURL url, std::string method) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + Q_ASSERT(!m_delegate); + + QWebEngineUrlSchemeHandler *schemeHandler = 0; + QSharedPointer<const BrowserContextAdapter> browserContext = m_adapter.toStrongRef(); + if (browserContext) + schemeHandler = browserContext->customUrlSchemeHandlers()[toQByteArray(m_scheme)]; + if (schemeHandler) { + m_delegate = new URLRequestCustomJobDelegate(this, toQt(url), + QByteArray::fromStdString(method)); + QWebEngineUrlRequestJob *requestJob = new QWebEngineUrlRequestJob(m_delegate); + schemeHandler->requestStarted(requestJob); + } +} + +} // namespace diff --git a/src/core/url_request_custom_job_proxy.h b/src/core/url_request_custom_job_proxy.h new file mode 100644 index 000000000..3ea30a4e1 --- /dev/null +++ b/src/core/url_request_custom_job_proxy.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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_PROXY_H_ +#define URL_REQUEST_CUSTOM_JOB_PROXY_H_ + +#include "base/memory/weak_ptr.h" +#include "url/gurl.h" +#include <QtCore/QWeakPointer> + +QT_FORWARD_DECLARE_CLASS(QIODevice) + +namespace QtWebEngineCore { + +class URLRequestCustomJob; +class URLRequestCustomJobDelegate; +class BrowserContextAdapter; + +// Used to comunicate between URLRequestCustomJob living on the IO thread +// and URLRequestCustomJobDelegate living on the UI thread. +class URLRequestCustomJobProxy + : public base::RefCountedThreadSafe<URLRequestCustomJobProxy> { + +public: + URLRequestCustomJobProxy(URLRequestCustomJob *job, + const std::string &scheme, + QWeakPointer<const BrowserContextAdapter> adapter); + ~URLRequestCustomJobProxy(); + + // Called from URLRequestCustomJobDelegate via post: + //void setReplyCharset(const std::string &); + void reply(std::string mimeType, QIODevice *device); + void redirect(GURL url); + void abort(); + void fail(int error); + void release(); + void initialize(GURL url, std::string method); + void readyRead(); + + // IO thread owned: + URLRequestCustomJob *m_job; + bool m_started; + + // UI thread owned: + std::string m_scheme; + URLRequestCustomJobDelegate *m_delegate; + QWeakPointer<const BrowserContextAdapter> m_adapter; +}; + +} // namespace QtWebEngineCore + +#endif // URL_REQUEST_CUSTOM_JOB_PROXY_H_ diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index b301622d4..e6a97b8bc 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -50,7 +50,6 @@ #include "browser_context_qt.h" #include "download_manager_delegate_qt.h" #include "media_capture_devices_dispatcher.h" -#include "pdfium_document_wrapper_qt.h" #include "print_view_manager_qt.h" #include "qwebenginecallback_p.h" #include "renderer_host/web_channel_ipc_transport_host.h" @@ -83,6 +82,8 @@ #include "content/public/common/web_preferences.h" #include "third_party/WebKit/public/web/WebFindOptions.h" #include "printing/features/features.h" +#include "ui/base/clipboard/clipboard.h" +#include "ui/base/clipboard/custom_data_helper.h" #include "ui/gfx/font_render_params.h" #include <QDir> @@ -90,6 +91,7 @@ #include <QPageLayout> #include <QStringList> #include <QStyleHints> +#include <QTimer> #include <QVariant> #include <QtCore/qelapsedtimer.h> #include <QtCore/qmimedata.h> @@ -101,6 +103,12 @@ namespace QtWebEngineCore { +#define CHECK_VALID_RENDER_WIDGET_HOST_VIEW(render_view_host) \ + if (!render_view_host->IsRenderViewLive() && render_view_host->GetWidget()->GetView()) { \ + qWarning("Ignore navigation due to terminated render process with invalid RenderWidgetHostView."); \ + return; \ + } + static const int kTestWindowWidth = 800; static const int kTestWindowHeight = 600; static const int kHistoryStreamVersion = 3; @@ -109,37 +117,37 @@ static QVariant fromJSValue(const base::Value *result) { QVariant ret; switch (result->GetType()) { - case base::Value::TYPE_NULL: + case base::Value::Type::NONE: break; - case base::Value::TYPE_BOOLEAN: + case base::Value::Type::BOOLEAN: { bool out; if (result->GetAsBoolean(&out)) ret.setValue(out); break; } - case base::Value::TYPE_INTEGER: + case base::Value::Type::INTEGER: { int out; if (result->GetAsInteger(&out)) ret.setValue(out); break; } - case base::Value::TYPE_DOUBLE: + case base::Value::Type::DOUBLE: { double out; if (result->GetAsDouble(&out)) ret.setValue(out); break; } - case base::Value::TYPE_STRING: + case base::Value::Type::STRING: { base::string16 out; if (result->GetAsString(&out)) ret.setValue(toQt(out)); break; } - case base::Value::TYPE_LIST: + case base::Value::Type::LIST: { const base::ListValue *out; if (result->GetAsList(&out)) { @@ -154,7 +162,7 @@ static QVariant fromJSValue(const base::Value *result) } break; } - case base::Value::TYPE_DICTIONARY: + case base::Value::Type::DICTIONARY: { const base::DictionaryValue *out; if (result->GetAsDictionary(&out)) { @@ -168,10 +176,9 @@ static QVariant fromJSValue(const base::Value *result) } break; } - case base::Value::TYPE_BINARY: + case base::Value::Type::BINARY: { - const base::BinaryValue *out = static_cast<const base::BinaryValue*>(result); - QByteArray data(out->GetBuffer(), out->GetSize()); + QByteArray data(result->GetBlob().data(), result->GetBlob().size()); ret.setValue(data); break; } @@ -350,7 +357,7 @@ WebContentsAdapterPrivate::WebContentsAdapterPrivate() , adapterClient(0) , nextRequestId(CallbackDirectory::ReservedCallbackIdsEnd) , lastFindRequestId(0) - , currentDropAction(blink::WebDragOperationNone) + , currentDropAction(blink::kWebDragOperationNone) { } @@ -501,14 +508,16 @@ void WebContentsAdapter::stop() void WebContentsAdapter::reload() { Q_D(WebContentsAdapter); - d->webContents->GetController().Reload(/*checkRepost = */false); + CHECK_VALID_RENDER_WIDGET_HOST_VIEW(d->webContents->GetRenderViewHost()); + d->webContents->GetController().Reload(content::ReloadType::NORMAL, /*checkRepost = */false); focusIfNecessary(); } void WebContentsAdapter::reloadAndBypassCache() { Q_D(WebContentsAdapter); - d->webContents->GetController().ReloadBypassingCache(/*checkRepost = */false); + CHECK_VALID_RENDER_WIDGET_HOST_VIEW(d->webContents->GetRenderViewHost()); + d->webContents->GetController().Reload(content::ReloadType::BYPASSING_CACHE, /*checkRepost = */false); focusIfNecessary(); } @@ -520,6 +529,9 @@ void WebContentsAdapter::load(const QUrl &url) void WebContentsAdapter::load(const QWebEngineHttpRequest &request) { + Q_D(WebContentsAdapter); + CHECK_VALID_RENDER_WIDGET_HOST_VIEW(d->webContents->GetRenderViewHost()); + // 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 @@ -533,7 +545,6 @@ void WebContentsAdapter::load(const QWebEngineHttpRequest &request) LoadRecursionGuard guard(this); Q_UNUSED(guard); - Q_D(WebContentsAdapter); GURL gurl = toGurl(request.url()); // Add URL scheme if missing from view-source URL. @@ -583,13 +594,35 @@ void WebContentsAdapter::load(const QWebEngineHttpRequest &request) params.extra_headers += (*it).toStdString() + ": " + request.header(*it).toStdString(); } - d->webContents->GetController().LoadURLWithParams(params); - focusIfNecessary(); + bool resizeNeeded = false; + if (request.url().hasFragment()) { + if (content::RenderWidgetHostView *rwhv = webContents()->GetRenderWidgetHostView()) { + const gfx::Size &viewportSize = rwhv->GetVisibleViewportSize(); + resizeNeeded = (viewportSize.width() == 0 || viewportSize.height() == 0); + } + } + + auto navigate = [this, params]() { + Q_D(WebContentsAdapter); + webContents()->GetController().LoadURLWithParams(params); + // Follow chrome::Navigate and invalidate the URL immediately. + d->webContentsDelegate->NavigationStateChanged(webContents(), content::INVALIDATE_TYPE_URL); + focusIfNecessary(); + }; + + if (resizeNeeded) { + // Schedule navigation on the event loop. + QTimer::singleShot(0, navigate); + } else { + navigate(); + } } void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl) { Q_D(WebContentsAdapter); + CHECK_VALID_RENDER_WIDGET_HOST_VIEW(d->webContents->GetRenderViewHost()); + QByteArray encodedData = data.toPercentEncoding(); std::string urlString; if (!mimeType.isEmpty()) @@ -612,7 +645,7 @@ void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeT params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE; d->webContents->GetController().LoadURLWithParams(params); focusIfNecessary(); - d->webContents->Unselect(); + d->webContents->CollapseSelection(); } void WebContentsAdapter::save(const QString &filePath, int savePageFormat) @@ -625,7 +658,7 @@ void WebContentsAdapter::save(const QString &filePath, int savePageFormat) QUrl WebContentsAdapter::activeUrl() const { Q_D(const WebContentsAdapter); - return toQt(d->webContents->GetLastCommittedURL()); + return d->webContentsDelegate->url(); } QUrl WebContentsAdapter::requestedUrl() const @@ -660,7 +693,7 @@ QUrl WebContentsAdapter::iconUrl() const QString WebContentsAdapter::pageTitle() const { Q_D(const WebContentsAdapter); - return toQt(d->webContents->GetTitle()); + return d->webContentsDelegate->title(); } QString WebContentsAdapter::selectedText() const @@ -720,12 +753,13 @@ void WebContentsAdapter::requestClose() void WebContentsAdapter::unselect() { Q_D(const WebContentsAdapter); - d->webContents->Unselect(); + d->webContents->CollapseSelection(); } void WebContentsAdapter::navigateToIndex(int offset) { Q_D(WebContentsAdapter); + CHECK_VALID_RENDER_WIDGET_HOST_VIEW(d->webContents->GetRenderViewHost()); d->webContents->GetController().GoToIndex(offset); focusIfNecessary(); } @@ -733,6 +767,7 @@ void WebContentsAdapter::navigateToIndex(int offset) void WebContentsAdapter::navigateToOffset(int offset) { Q_D(WebContentsAdapter); + CHECK_VALID_RENDER_WIDGET_HOST_VIEW(d->webContents->GetRenderViewHost()); d->webContents->GetController().GoToOffset(offset); focusIfNecessary(); } @@ -902,8 +937,8 @@ quint64 WebContentsAdapter::findText(const QString &subString, bool caseSensitiv blink::WebFindOptions options; options.forward = !findBackward; - options.matchCase = caseSensitively; - options.findNext = subString == d->webContentsDelegate->lastSearchedString(); + options.match_case = caseSensitively; + options.find_next = subString == d->webContentsDelegate->lastSearchedString(); d->webContentsDelegate->setLastSearchedString(subString); // Find already allows a request ID as input, but only as an int. @@ -918,9 +953,6 @@ void WebContentsAdapter::stopFinding() { Q_D(WebContentsAdapter); d->webContentsDelegate->setLastSearchedString(QString()); - // Clear any previous selection, - // but keep the renderer blue rectangle selection just like Chromium does. - d->webContents->Unselect(); d->webContents->StopFinding(content::STOP_FIND_ACTION_KEEP_SELECTION); } @@ -945,9 +977,26 @@ void WebContentsAdapter::download(const QUrl &url, const QString &suggestedFileN dlmd->markNextDownloadAsUserRequested(); dlm->SetDelegate(dlmd); + net::NetworkTrafficAnnotationTag traffic_annotation = + net::DefineNetworkTrafficAnnotation( + "WebContentsAdapter::download", R"( + semantics { + sender: "User" + description: + "User requested download" + trigger: "User." + data: "Anything." + destination: OTHER + } + policy { + cookies_allowed: YES + cookies_store: "user" + setting: + "It's possible not to use this feature." + })"); GURL gurl = toGurl(url); std::unique_ptr<content::DownloadUrlParameters> params( - content::DownloadUrlParameters::CreateForWebContentsMainFrame(webContents(), gurl)); + content::DownloadUrlParameters::CreateForWebContentsMainFrame(webContents(), gurl, traffic_annotation)); params->set_suggested_name(toString16(suggestedFileName)); @@ -985,11 +1034,11 @@ void WebContentsAdapter::copyImageAt(const QPoint &location) d->webContents->GetRenderViewHost()->GetMainFrame()->CopyImageAt(location.x(), location.y()); } -ASSERT_ENUMS_MATCH(WebContentsAdapter::MediaPlayerNoAction, blink::WebMediaPlayerAction::Unknown) -ASSERT_ENUMS_MATCH(WebContentsAdapter::MediaPlayerPlay, blink::WebMediaPlayerAction::Play) -ASSERT_ENUMS_MATCH(WebContentsAdapter::MediaPlayerMute, blink::WebMediaPlayerAction::Mute) -ASSERT_ENUMS_MATCH(WebContentsAdapter::MediaPlayerLoop, blink::WebMediaPlayerAction::Loop) -ASSERT_ENUMS_MATCH(WebContentsAdapter::MediaPlayerControls, blink::WebMediaPlayerAction::Controls) +ASSERT_ENUMS_MATCH(WebContentsAdapter::MediaPlayerNoAction, blink::WebMediaPlayerAction::kUnknown) +ASSERT_ENUMS_MATCH(WebContentsAdapter::MediaPlayerPlay, blink::WebMediaPlayerAction::kPlay) +ASSERT_ENUMS_MATCH(WebContentsAdapter::MediaPlayerMute, blink::WebMediaPlayerAction::kMute) +ASSERT_ENUMS_MATCH(WebContentsAdapter::MediaPlayerLoop, blink::WebMediaPlayerAction::kLoop) +ASSERT_ENUMS_MATCH(WebContentsAdapter::MediaPlayerControls, blink::WebMediaPlayerAction::kControls) void WebContentsAdapter::executeMediaPlayerActionAt(const QPoint &location, MediaPlayerAction action, bool enable) { @@ -1180,18 +1229,23 @@ static QMimeData *mimeDataFromDropData(const content::DropData &dropData) mimeData->setHtml(toQt(dropData.html.string())); if (dropData.url.is_valid()) mimeData->setUrls(QList<QUrl>() << toQt(dropData.url)); + if (!dropData.custom_data.empty()) { + base::Pickle pickle; + ui::WriteCustomDataToPickle(dropData.custom_data, &pickle); + mimeData->setData(toQt(ui::Clipboard::GetWebCustomDataFormatType().ToString()), QByteArray((const char*)pickle.data(), pickle.size())); + } return mimeData; } static blink::WebDragOperationsMask toWeb(const Qt::DropActions action) { - int result = blink::WebDragOperationNone; + int result = blink::kWebDragOperationNone; if (action & Qt::CopyAction) - result |= blink::WebDragOperationCopy; + result |= blink::kWebDragOperationCopy; if (action & Qt::LinkAction) - result |= blink::WebDragOperationLink; + result |= blink::kWebDragOperationLink; if (action & Qt::MoveAction) - result |= blink::WebDragOperationMove; + result |= blink::kWebDragOperationMove; return static_cast<blink::WebDragOperationsMask>(result); } @@ -1209,16 +1263,14 @@ void WebContentsAdapter::startDragging(QObject *dragSource, const content::DropD d->currentDropData.reset(new content::DropData(dropData)); d->currentDropData->download_metadata.clear(); d->currentDropData->file_contents.clear(); - d->currentDropData->file_description_filename.clear(); + d->currentDropData->file_contents_content_disposition.clear(); - d->currentDropAction = blink::WebDragOperationNone; + d->currentDropAction = blink::kWebDragOperationNone; 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](){ dValid = false; -#if (QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)) QDrag::cancel(); -#endif }); QMimeData *mimeData = mimeDataFromDropData(*d->currentDropData); @@ -1266,7 +1318,8 @@ bool WebContentsAdapter::handleDropDataFileContents(const content::DropData &dro } } - const QString &fileName = toQt(dropData.file_description_filename); + const auto maybeFilename = dropData.GetSafeFilenameForImageFileContents(); + const QString fileName = maybeFilename ? toQt(maybeFilename->AsUTF16Unsafe()) : QString(); #if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)) const QString &filePath = d->dndTmpDir->filePath(fileName); #else @@ -1300,6 +1353,10 @@ static void fillDropDataFromMimeData(content::DropData *dropData, const QMimeDat dropData->html = toNullableString16(mimeData->html()); if (mimeData->hasText()) dropData->text = toNullableString16(mimeData->text()); + if (mimeData->hasFormat(toQt(ui::Clipboard::GetWebCustomDataFormatType().ToString()))) { + QByteArray customData = mimeData->data(toQt(ui::Clipboard::GetWebCustomDataFormatType().ToString())); + ui::ReadCustomDataIntoMap(customData.constData(), customData.length(), &dropData->custom_data); + } } void WebContentsAdapter::enterDrag(QDragEnterEvent *e, const QPoint &screenPos) @@ -1321,11 +1378,11 @@ void WebContentsAdapter::enterDrag(QDragEnterEvent *e, const QPoint &screenPos) Qt::DropAction toQt(blink::WebDragOperation op) { - if (op & blink::WebDragOperationCopy) + if (op & blink::kWebDragOperationCopy) return Qt::CopyAction; - if (op & blink::WebDragOperationLink) + if (op & blink::kWebDragOperationLink) return Qt::LinkAction; - if (op & blink::WebDragOperationMove || op & blink::WebDragOperationDelete) + if (op & blink::kWebDragOperationMove || op & blink::kWebDragOperationDelete) return Qt::MoveAction; return Qt::IgnoreAction; } @@ -1334,11 +1391,11 @@ static int toWeb(Qt::MouseButtons buttons) { int result = 0; if (buttons & Qt::LeftButton) - result |= blink::WebInputEvent::LeftButtonDown; + result |= blink::WebInputEvent::kLeftButtonDown; if (buttons & Qt::RightButton) - result |= blink::WebInputEvent::RightButtonDown; + result |= blink::WebInputEvent::kRightButtonDown; if (buttons & Qt::MiddleButton) - result |= blink::WebInputEvent::MiddleButtonDown; + result |= blink::WebInputEvent::kMiddleButtonDown; return result; } @@ -1346,13 +1403,13 @@ static int toWeb(Qt::KeyboardModifiers modifiers) { int result = 0; if (modifiers & Qt::ShiftModifier) - result |= blink::WebInputEvent::ShiftKey; + result |= blink::WebInputEvent::kShiftKey; if (modifiers & Qt::ControlModifier) - result |= blink::WebInputEvent::ControlKey; + result |= blink::WebInputEvent::kControlKey; if (modifiers & Qt::AltModifier) - result |= blink::WebInputEvent::AltKey; + result |= blink::WebInputEvent::kAltKey; if (modifiers & Qt::MetaModifier) - result |= blink::WebInputEvent::MetaKey; + result |= blink::WebInputEvent::kMetaKey; return result; } @@ -1412,7 +1469,7 @@ void WebContentsAdapter::leaveDrag() { Q_D(WebContentsAdapter); content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); - rvh->GetWidget()->DragTargetDragLeave(); + rvh->GetWidget()->DragTargetDragLeave(d->lastDragClientPos, d->lastDragScreenPos); d->currentDropData.reset(); } @@ -1500,13 +1557,15 @@ ASSERT_ENUMS_MATCH(WebContentsAdapterClient::SaveToDiskDisposition, WindowOpenDi ASSERT_ENUMS_MATCH(WebContentsAdapterClient::OffTheRecordDisposition, WindowOpenDisposition::OFF_THE_RECORD) ASSERT_ENUMS_MATCH(WebContentsAdapterClient::IgnoreActionDisposition, WindowOpenDisposition::IGNORE_ACTION) -ASSERT_ENUMS_MATCH(ReferrerPolicy::Always, blink::WebReferrerPolicyAlways) -ASSERT_ENUMS_MATCH(ReferrerPolicy::Default, blink::WebReferrerPolicyDefault) -ASSERT_ENUMS_MATCH(ReferrerPolicy::NoReferrerWhenDowngrade, blink::WebReferrerPolicyNoReferrerWhenDowngrade) -ASSERT_ENUMS_MATCH(ReferrerPolicy::Never, blink::WebReferrerPolicyNever) -ASSERT_ENUMS_MATCH(ReferrerPolicy::Origin, blink::WebReferrerPolicyOrigin) -ASSERT_ENUMS_MATCH(ReferrerPolicy::OriginWhenCrossOrigin, blink::WebReferrerPolicyOriginWhenCrossOrigin) -ASSERT_ENUMS_MATCH(ReferrerPolicy::NoReferrerWhenDowngradeOriginWhenCrossOrigin, blink::WebReferrerPolicyNoReferrerWhenDowngradeOriginWhenCrossOrigin) -ASSERT_ENUMS_MATCH(ReferrerPolicy::Last, blink::WebReferrerPolicyLast) +ASSERT_ENUMS_MATCH(ReferrerPolicy::Always, blink::kWebReferrerPolicyAlways) +ASSERT_ENUMS_MATCH(ReferrerPolicy::Default, blink::kWebReferrerPolicyDefault) +ASSERT_ENUMS_MATCH(ReferrerPolicy::NoReferrerWhenDowngrade, blink::kWebReferrerPolicyNoReferrerWhenDowngrade) +ASSERT_ENUMS_MATCH(ReferrerPolicy::Never, blink::kWebReferrerPolicyNever) +ASSERT_ENUMS_MATCH(ReferrerPolicy::Origin, blink::kWebReferrerPolicyOrigin) +ASSERT_ENUMS_MATCH(ReferrerPolicy::OriginWhenCrossOrigin, blink::kWebReferrerPolicyOriginWhenCrossOrigin) +ASSERT_ENUMS_MATCH(ReferrerPolicy::NoReferrerWhenDowngradeOriginWhenCrossOrigin, blink::kWebReferrerPolicyNoReferrerWhenDowngradeOriginWhenCrossOrigin) +ASSERT_ENUMS_MATCH(ReferrerPolicy::SameOrigin, blink::kWebReferrerPolicySameOrigin) +ASSERT_ENUMS_MATCH(ReferrerPolicy::StrictOrigin, blink::kWebReferrerPolicyStrictOrigin) +ASSERT_ENUMS_MATCH(ReferrerPolicy::Last, blink::kWebReferrerPolicyLast) } // namespace QtWebEngineCore diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h index 3cc5350df..f2f1d28d1 100644 --- a/src/core/web_contents_adapter_client.h +++ b/src/core/web_contents_adapter_client.h @@ -80,7 +80,9 @@ enum class ReferrerPolicy { Origin, OriginWhenCrossOrigin, NoReferrerWhenDowngradeOriginWhenCrossOrigin, - Last = NoReferrerWhenDowngradeOriginWhenCrossOrigin, + SameOrigin, + StrictOrigin, + Last = StrictOrigin, }; class WebEngineContextMenuSharedData : public QSharedData { @@ -101,6 +103,7 @@ public: uint mediaFlags; QPoint pos; QUrl linkUrl; + QUrl unfilteredLinkUrl; QUrl mediaUrl; QString linkText; QString selectedText; @@ -170,6 +173,14 @@ public: return d->linkUrl; } + void setUnfilteredLinkUrl(const QUrl &url) { + d->unfilteredLinkUrl = url; + } + + QUrl unfilteredLinkUrl() const { + return d->unfilteredLinkUrl; + } + void setLinkText(const QString &text) { d->linkText = text; } @@ -307,7 +318,7 @@ public: IgnoreActionDisposition = 9, }; - // Must match the values in javascript_message_type.h. + // Must match the values in javascript_dialog_type.h. enum JavascriptDialogType { AlertDialog, ConfirmDialog, @@ -349,6 +360,8 @@ public: MediaNone = 0, MediaAudioCapture = 0x01, MediaVideoCapture = 0x02, + MediaDesktopAudioCapture = 0x04, + MediaDesktopVideoCapture = 0x08 }; Q_DECLARE_FLAGS(MediaRequestFlags, MediaRequestFlag) @@ -376,7 +389,7 @@ public: virtual bool isBeingAdopted() = 0; virtual void close() = 0; virtual void windowCloseRejected() = 0; - virtual bool contextMenuRequested(const WebEngineContextMenuData &) = 0; + virtual void contextMenuRequested(const WebEngineContextMenuData &) = 0; virtual void navigationRequested(int navigationType, const QUrl &url, int &navigationRequestAction, bool isMainFrame) = 0; virtual void requestFullScreenMode(const QUrl &origin, bool fullscreen) = 0; virtual bool isFullScreenMode() const = 0; diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index 4fe877e67..f51a6dff3 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -63,6 +63,7 @@ #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/public/browser/invalidate_type.h" #include "content/public/browser/navigation_entry.h" +#include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" @@ -72,7 +73,6 @@ #include "content/public/common/frame_navigate_params.h" #include "content/public/common/url_constants.h" #include "content/public/common/web_preferences.h" -#include "ui/events/latency_info.h" #include <QDesktopServices> #include <QTimer> @@ -103,6 +103,7 @@ WebContentsDelegateQt::WebContentsDelegateQt(content::WebContents *webContents, : m_viewClient(adapterClient) , m_lastReceivedFindReply(0) , m_faviconManager(new FaviconManager(new FaviconManagerPrivate(webContents, adapterClient))) + , m_lastLoadProgress(-1) { webContents->SetDelegate(this); Observe(webContents); @@ -127,6 +128,7 @@ content::WebContents *WebContentsDelegateQt::OpenURLFromTab(content::WebContents load_url_params.extra_headers = params.extra_headers; load_url_params.should_replace_current_entry = params.should_replace_current_entry; load_url_params.is_renderer_initiated = params.is_renderer_initiated; + load_url_params.started_from_context_menu = params.started_from_context_menu; load_url_params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE; if (params.uses_post) { load_url_params.load_type = content::NavigationController::LOAD_TYPE_HTTP_POST; @@ -139,10 +141,21 @@ content::WebContents *WebContentsDelegateQt::OpenURLFromTab(content::WebContents void WebContentsDelegateQt::NavigationStateChanged(content::WebContents* source, content::InvalidateTypes changed_flags) { - if (changed_flags & content::INVALIDATE_TYPE_URL) - m_viewClient->urlChanged(toQt(source->GetVisibleURL())); - if (changed_flags & content::INVALIDATE_TYPE_TITLE) - m_viewClient->titleChanged(toQt(source->GetTitle())); + if (changed_flags & content::INVALIDATE_TYPE_URL) { + QUrl newUrl = toQt(source->GetVisibleURL()); + if (m_url != newUrl) { + m_url = newUrl; + m_viewClient->urlChanged(m_url); + } + } + + if (changed_flags & content::INVALIDATE_TYPE_TITLE) { + QString newTitle = toQt(source->GetTitle()); + if (m_title != newTitle) { + m_title = newTitle; + m_viewClient->titleChanged(m_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 @@ -154,20 +167,6 @@ void WebContentsDelegateQt::NavigationStateChanged(content::WebContents* source, } } -bool WebContentsDelegateQt::ShouldPreserveAbortedURLs(content::WebContents *source) -{ - Q_UNUSED(source) - - // Allow failed URLs to stick around in the URL bar, but only when the error-page is enabled. - WebEngineSettings *settings = m_viewClient->webEngineSettings(); - bool isErrorPageEnabled = settings->testAttribute(settings->Attribute::ErrorPageEnabled); - - if (isErrorPageEnabled) - return true; - - return false; -} - void WebContentsDelegateQt::AddNewContents(content::WebContents* source, content::WebContents* new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture, bool* was_blocked) { Q_UNUSED(source) @@ -179,14 +178,18 @@ void WebContentsDelegateQt::AddNewContents(content::WebContents* source, content void WebContentsDelegateQt::CloseContents(content::WebContents *source) { m_viewClient->close(); - GetJavaScriptDialogManager(source)->CancelDialogs(source, /* whatever?: */false, false); + GetJavaScriptDialogManager(source)->CancelDialogs(source, /* whatever?: */false); } -void WebContentsDelegateQt::LoadProgressChanged(content::WebContents* source, double progress) +void WebContentsDelegateQt::LoadProgressChanged(content::WebContents */*source*/, double progress) { if (!m_loadingErrorFrameList.isEmpty()) return; - m_viewClient->loadProgressChanged(qRound(progress * 100)); + 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); } void WebContentsDelegateQt::HandleKeyboardEvent(content::WebContents *, const content::NativeWebKeyboardEvent &event) @@ -201,59 +204,113 @@ void WebContentsDelegateQt::RenderFrameDeleted(content::RenderFrameHost *render_ m_loadingErrorFrameList.removeOne(render_frame_host->GetRoutingID()); } -void WebContentsDelegateQt::DidStartProvisionalLoadForFrame(content::RenderFrameHost* render_frame_host, const GURL& validated_url, bool is_error_page, bool is_iframe_srcdoc) +void WebContentsDelegateQt::EmitLoadStarted(const QUrl &url, bool isErrorPage) { - if (is_error_page) { - m_loadingErrorFrameList.append(render_frame_host->GetRoutingID()); - - // Trigger LoadStarted signal for main frame's error page only. - if (!render_frame_host->GetParent()) { - m_faviconManager->resetCandidates(); - m_viewClient->loadStarted(toQt(validated_url), true); - } + if (m_lastLoadProgress >= 0) // already running + return; + m_viewClient->loadStarted(url, isErrorPage); + m_viewClient->loadProgressChanged(0); + m_lastLoadProgress = 0; +} +void WebContentsDelegateQt::DidStartNavigation(content::NavigationHandle *navigation_handle) +{ + if (!navigation_handle->IsInMainFrame()) return; + + // Suppress extra loadStarted signal for data URL with specified base URL. + if (navigation_handle->GetURL().SchemeIs(url::kDataScheme)) { + content::NavigationEntry *pending_entry = navigation_handle->GetWebContents()->GetController().GetPendingEntry(); + + if (pending_entry && !pending_entry->GetBaseURLForDataURL().is_empty() && + navigation_handle->GetURL() == pending_entry->GetURL()) { + return; + } } - if (render_frame_host->GetParent()) - return; + // Error-pages are not reported as separate started navigations. + Q_ASSERT(!navigation_handle->IsErrorPage()); m_loadingErrorFrameList.clear(); m_faviconManager->resetCandidates(); - m_viewClient->loadStarted(toQt(validated_url)); + EmitLoadStarted(toQt(navigation_handle->GetURL())); +} + +void WebContentsDelegateQt::EmitLoadFinished(bool success, const QUrl &url, bool isErrorPage, int errorCode, const QString &errorDescription) +{ + if (m_lastLoadProgress < 0) // not currently running + return; + m_lastLoadProgress = -1; + m_viewClient->loadProgressChanged(100); + m_viewClient->loadFinished(success, url, isErrorPage, errorCode, errorDescription); } -void WebContentsDelegateQt::DidCommitProvisionalLoadForFrame(content::RenderFrameHost* render_frame_host, const GURL& url, ui::PageTransition transition_type) +void WebContentsDelegateQt::DidFinishNavigation(content::NavigationHandle *navigation_handle) { - // Make sure that we don't set the findNext WebFindOptions on a new frame. - m_lastSearchedString = QString(); + if (!navigation_handle->IsInMainFrame()) + return; - // This is currently used for canGoBack/Forward values, which is flattened across frames. For other purposes we might have to pass is_main_frame. - m_viewClient->loadCommitted(); + if (navigation_handle->HasCommitted() && !navigation_handle->IsErrorPage()) { + BrowserContextAdapter *browserContextAdapter = m_viewClient->browserContextAdapter().data(); + // VisistedLinksMaster asserts !IsOffTheRecord(). + if (navigation_handle->ShouldUpdateHistory() && browserContextAdapter->trackVisitedLinks()) { + for (const GURL &url : navigation_handle->GetRedirectChain()) + browserContextAdapter->visitedLinksManager()->addUrl(url); + } + + // Make sure that we don't set the findNext WebFindOptions on a new frame. + m_lastSearchedString = QString(); + + // This is currently used for canGoBack/Forward values, which is flattened across frames. For other purposes we might have to pass is_main_frame. + m_viewClient->loadCommitted(); + } + // Success is reported by DidFinishLoad, but DidFailLoad is now dead code and needs to be handled below + if (navigation_handle->GetNetErrorCode() == net::OK) + return; + + // WebContentsObserver::DidFailLoad is not called any longer so we have to report the failure here. + const net::Error error_code = navigation_handle->GetNetErrorCode(); + const std::string error_description = net::ErrorToString(error_code); + didFailLoad(toQt(navigation_handle->GetURL()), error_code, toQt(error_description)); + + // 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); + + // If it is already committed we will not see another DidFinishNavigation call or a DidFinishLoad call. + if (navigation_handle->HasCommitted()) { + m_lastSearchedString = QString(); + m_viewClient->loadCommitted(); + } + } } -void WebContentsDelegateQt::DidFailProvisionalLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url, int error_code, const base::string16& error_description, bool was_ignored_by_handler) +void WebContentsDelegateQt::didFailLoad(const QUrl &url, int errorCode, const QString &errorDescription) { - DidFailLoad(render_frame_host, validated_url, error_code, error_description, was_ignored_by_handler); + m_viewClient->iconChanged(QUrl()); + EmitLoadFinished(false /* success */ , url, false /* isErrorPage */, errorCode, errorDescription); } void WebContentsDelegateQt::DidFailLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url, int error_code, const base::string16& error_description, bool was_ignored_by_handler) { Q_UNUSED(was_ignored_by_handler); + if (render_frame_host->GetParent()) + return; + 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()); - qCritical("Loading error-page failed. This shouldn't happen."); - if (!render_frame_host->GetParent()) - m_viewClient->loadFinished(false /* success */, toQt(validated_url), true /* isErrorPage */); - return; - } + m_viewClient->iconChanged(QUrl()); - if (render_frame_host->GetParent()) + EmitLoadFinished(false /* success */, toQt(validated_url), true /* isErrorPage */); return; + } - m_viewClient->iconChanged(QUrl()); - m_viewClient->loadFinished(false /* success */ , toQt(validated_url), false /* isErrorPage */, error_code, toQt(error_description)); - m_viewClient->loadProgressChanged(0); + didFailLoad(toQt(validated_url), error_code, toQt(error_description)); } void WebContentsDelegateQt::DidFinishLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url) @@ -265,7 +322,7 @@ void WebContentsDelegateQt::DidFinishLoad(content::RenderFrameHost* render_frame // Trigger LoadFinished signal for main frame's error page only. if (!render_frame_host->GetParent()) - m_viewClient->loadFinished(true /* success */, toQt(validated_url), true /* isErrorPage */); + EmitLoadFinished(true /* success */, toQt(validated_url), true /* isErrorPage */); return; } @@ -276,8 +333,7 @@ void WebContentsDelegateQt::DidFinishLoad(content::RenderFrameHost* render_frame if (!m_faviconManager->hasCandidate()) m_viewClient->iconChanged(QUrl()); - m_viewClient->loadProgressChanged(100); - m_viewClient->loadFinished(true, toQt(validated_url)); + EmitLoadFinished(true, toQt(validated_url)); } void WebContentsDelegateQt::DidUpdateFaviconURL(const std::vector<content::FaviconURL> &candidates) @@ -295,9 +351,12 @@ void WebContentsDelegateQt::DidUpdateFaviconURL(const std::vector<content::Favic m_faviconManager->update(faviconCandidates); } -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* new_contents) +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 */*new_contents*/) { - this->m_initialTargetUrl = toQt(target_url); + m_initialTargetUrl = toQt(target_url); } content::ColorChooser *WebContentsDelegateQt::OpenColorChooser(content::WebContents *source, SkColor color, const std::vector<content::ColorSuggestion> &suggestion) @@ -393,14 +452,6 @@ void WebContentsDelegateQt::UpdateTargetURL(content::WebContents* source, const m_viewClient->didUpdateTargetURL(toQt(url)); } -void WebContentsDelegateQt::DidNavigateAnyFrame(content::RenderFrameHost* render_frame_host, const content::LoadCommittedDetails& details, const content::FrameNavigateParams& params) -{ - // VisistedLinksMaster asserts !IsOffTheRecord(). - if (!params.should_update_history || !m_viewClient->browserContextAdapter()->trackVisitedLinks()) - return; - m_viewClient->browserContextAdapter()->visitedLinksManager()->addUrl(params.url); -} - void WebContentsDelegateQt::WasShown() { web_cache::WebCacheManager::GetInstance()->ObserveActivity(web_contents()->GetRenderProcessHost()->GetID()); @@ -421,6 +472,13 @@ void WebContentsDelegateQt::DidFirstVisuallyNonEmptyPaint() } } +void WebContentsDelegateQt::ActivateContents(content::WebContents* contents) +{ + WebEngineSettings *settings = m_viewClient->webEngineSettings(); + if (settings->testAttribute(settings->Attribute::AllowWindowActivationFromJavaScript)) + contents->Focus(); +} + void WebContentsDelegateQt::RequestToLockMouse(content::WebContents *web_contents, bool user_gesture, bool last_unlocked_by_target) { Q_UNUSED(user_gesture); @@ -499,6 +557,10 @@ void WebContentsDelegateQt::BeforeUnloadFired(content::WebContents *tab, bool pr m_viewClient->windowCloseRejected(); } +void WebContentsDelegateQt::BeforeUnloadFired(const base::TimeTicks &proceed_time) { + Q_UNUSED(proceed_time); +} + bool WebContentsDelegateQt::CheckMediaAccessPermission(content::WebContents *web_contents, const GURL& security_origin, content::MediaStreamType type) { switch (type) { @@ -518,4 +580,8 @@ FaviconManager *WebContentsDelegateQt::faviconManager() return m_faviconManager.data(); } +WebEngineSettings *WebContentsDelegateQt::webEngineSettings() const { + return m_viewClient->webEngineSettings(); +} + } // namespace QtWebEngineCore diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h index 913bf356c..8440ec053 100644 --- a/src/core/web_contents_delegate_qt.h +++ b/src/core/web_contents_delegate_qt.h @@ -68,6 +68,7 @@ namespace content { namespace QtWebEngineCore { class WebContentsAdapterClient; +class WebEngineSettings; class SavePageInfo { @@ -96,6 +97,9 @@ public: void setLastSearchedString(const QString &s) { m_lastSearchedString = s; } int lastReceivedFindReply() const { return m_lastReceivedFindReply; } + QUrl url() const { return m_url; } + 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; @@ -104,7 +108,8 @@ public: void LoadProgressChanged(content::WebContents* source, double progress) override; void HandleKeyboardEvent(content::WebContents *source, const content::NativeWebKeyboardEvent &event) override; content::ColorChooser *OpenColorChooser(content::WebContents *source, SkColor color, const std::vector<content::ColorSuggestion> &suggestion) 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; + 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) override; void ExitFullscreenModeForTab(content::WebContents*) override; @@ -117,7 +122,6 @@ public: bool IsPopupOrPanel(const content::WebContents *source) const override; void UpdateTargetURL(content::WebContents* source, const GURL& url) override; void RequestToLockMouse(content::WebContents *web_contents, bool user_gesture, bool last_unlocked_by_target) override; - bool ShouldPreserveAbortedURLs(content::WebContents *source) override; void ShowValidationMessage(content::WebContents *web_contents, const gfx::Rect &anchor_in_root_view, const base::string16 &main_text, const base::string16 &sub_text) override; void HideValidationMessage(content::WebContents *web_contents) override; void MoveValidationMessage(content::WebContents *web_contents, const gfx::Rect &anchor_in_root_view) override; @@ -126,18 +130,18 @@ public: // WebContentsObserver overrides void RenderFrameDeleted(content::RenderFrameHost *render_frame_host) override; - void DidStartProvisionalLoadForFrame(content::RenderFrameHost *render_frame_host, const GURL &validated_url, bool is_error_page, bool is_iframe_srcdoc) override; - void DidCommitProvisionalLoadForFrame(content::RenderFrameHost *render_frame_host, const GURL &url, ui::PageTransition transition_type) override; - void DidFailProvisionalLoad(content::RenderFrameHost *render_frame_host, const GURL &validated_url, - int error_code, const base::string16 &error_description, bool was_ignored_by_handler) override; + void DidStartNavigation(content::NavigationHandle *navigation_handle) override; + void DidFinishNavigation(content::NavigationHandle *navigation_handle) override; void DidFailLoad(content::RenderFrameHost *render_frame_host, const GURL &validated_url, int error_code, const base::string16 &error_description, bool was_ignored_by_handler) override; void DidFinishLoad(content::RenderFrameHost *render_frame_host, const GURL &validated_url) override; + void BeforeUnloadFired(const base::TimeTicks& proceed_time) override; void DidUpdateFaviconURL(const std::vector<content::FaviconURL> &candidates) override; - void DidNavigateAnyFrame(content::RenderFrameHost *render_frame_host, const content::LoadCommittedDetails &details, const content::FrameNavigateParams ¶ms) override; void WasShown() override; void DidFirstVisuallyNonEmptyPaint() override; + void ActivateContents(content::WebContents* contents) override; + void didFailLoad(const QUrl &url, int errorCode, const QString &errorDescription); void overrideWebPreferences(content::WebContents *, content::WebPreferences*); void allowCertificateError(const QSharedPointer<CertificateErrorController> &) ; void requestGeolocationPermission(const QUrl &requestingOrigin); @@ -147,8 +151,12 @@ public: void setSavePageInfo(const SavePageInfo &spi) { m_savePageInfo = spi; } const SavePageInfo &savePageInfo() { return m_savePageInfo; } + WebEngineSettings *webEngineSettings() const; + private: QWeakPointer<WebContentsAdapter> createWindow(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()); WebContentsAdapterClient *m_viewClient; QString m_lastSearchedString; @@ -158,6 +166,10 @@ private: SavePageInfo m_savePageInfo; QSharedPointer<FilePickerController> m_filePickerController; QUrl m_initialTargetUrl; + int m_lastLoadProgress; + + QUrl m_url; + QString m_title; }; } // namespace QtWebEngineCore diff --git a/src/core/web_contents_view_qt.cpp b/src/core/web_contents_view_qt.cpp index 86e839a7f..28f202e24 100644 --- a/src/core/web_contents_view_qt.cpp +++ b/src/core/web_contents_view_qt.cpp @@ -138,25 +138,25 @@ void WebContentsViewQt::SetInitialFocus() Focus(); } -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypeNone, blink::WebContextMenuData::MediaTypeNone) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypeImage, blink::WebContextMenuData::MediaTypeImage) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypeVideo, blink::WebContextMenuData::MediaTypeVideo) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypeAudio, blink::WebContextMenuData::MediaTypeAudio) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypeCanvas, blink::WebContextMenuData::MediaTypeCanvas) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypeFile, blink::WebContextMenuData::MediaTypeFile) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypePlugin, blink::WebContextMenuData::MediaTypePlugin) - -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaNone, blink::WebContextMenuData::MediaNone) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaInError, blink::WebContextMenuData::MediaInError) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaPaused, blink::WebContextMenuData::MediaPaused) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaMuted, blink::WebContextMenuData::MediaMuted) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaLoop, blink::WebContextMenuData::MediaLoop) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaCanSave, blink::WebContextMenuData::MediaCanSave) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaHasAudio, blink::WebContextMenuData::MediaHasAudio) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaCanToggleControls, blink::WebContextMenuData::MediaCanToggleControls) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaControls, blink::WebContextMenuData::MediaControls) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaCanPrint, blink::WebContextMenuData::MediaCanPrint) -ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaCanRotate, blink::WebContextMenuData::MediaCanRotate) +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::MediaNone, blink::WebContextMenuData::kMediaNone) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaInError, blink::WebContextMenuData::kMediaInError) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaPaused, blink::WebContextMenuData::kMediaPaused) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaMuted, blink::WebContextMenuData::kMediaMuted) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaLoop, blink::WebContextMenuData::kMediaLoop) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaCanSave, blink::WebContextMenuData::kMediaCanSave) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaHasAudio, blink::WebContextMenuData::kMediaHasAudio) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaCanToggleControls, blink::WebContextMenuData::kMediaCanToggleControls) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaControls, blink::WebContextMenuData::kMediaControls) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaCanPrint, blink::WebContextMenuData::kMediaCanPrint) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaCanRotate, blink::WebContextMenuData::kMediaCanRotate) static inline WebEngineContextMenuData fromParams(const content::ContextMenuParams ¶ms) { @@ -164,6 +164,7 @@ static inline WebEngineContextMenuData fromParams(const content::ContextMenuPara ret.setPosition(QPoint(params.x, params.y)); ret.setLinkUrl(toQt(params.link_url)); ret.setLinkText(toQt(params.link_text.data())); + ret.setUnfilteredLinkUrl(toQt(params.unfiltered_link_url)); ret.setSelectedText(toQt(params.selection_text.data())); ret.setMediaUrl(toQt(params.src_url)); ret.setMediaType((WebEngineContextMenuData::MediaType)params.media_type); @@ -200,11 +201,11 @@ void WebContentsViewQt::ShowContextMenu(content::RenderFrameHost *, const conten Qt::DropActions toQtDropActions(blink::WebDragOperationsMask ops) { Qt::DropActions result; - if (ops & blink::WebDragOperationCopy) + if (ops & blink::kWebDragOperationCopy) result |= Qt::CopyAction; - if (ops & blink::WebDragOperationLink) + if (ops & blink::kWebDragOperationLink) result |= Qt::LinkAction; - if (ops & blink::WebDragOperationMove || ops & blink::WebDragOperationDelete) + if (ops & blink::kWebDragOperationMove || ops & blink::kWebDragOperationDelete) result |= Qt::MoveAction; return result; } diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 6a8c8ae73..9199bd102 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -51,8 +51,9 @@ #if BUILDFLAG(ENABLE_BASIC_PRINTING) #include "chrome/browser/printing/print_job_manager.h" #endif // defined(ENABLE_BASIC_PRINTING) +#include "components/web_cache/browser/web_cache_manager.h" #include "content/browser/devtools/devtools_http_handler.h" -#include "content/browser/gpu/gpu_process_host.h" +#include "content/browser/gpu/gpu_main_thread_factory.h" #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/utility_process_host_impl.h" #include "content/gpu/in_process_gpu_thread.h" @@ -61,15 +62,18 @@ #include "content/public/browser/browser_main_runner.h" #include "content/public/browser/plugin_service.h" #include "content/public/browser/render_frame_host.h" +#include "content/public/common/content_features.h" #include "content/public/common/content_paths.h" #include "content/public/common/content_switches.h" #include "content/public/common/main_function_params.h" #include "content/renderer/in_process_renderer_thread.h" #include "content/utility/in_process_utility_thread.h" #include "gpu/command_buffer/service/gpu_switches.h" +#include "gpu/ipc/host/gpu_switches.h" #include "net/base/port_util.h" +#include "ppapi/features/features.h" #include "ui/events/event_switches.h" -#include "ui/native_theme/native_theme_switches.h" +#include "ui/native_theme/native_theme_features.h" #include "ui/gl/gl_switches.h" #if defined(OS_WIN) #include "sandbox/win/src/sandbox_types.h" @@ -163,7 +167,7 @@ bool usingQtQuick2DRenderer() return device != QLatin1String("default"); } #endif //QT_NO_OPENGL -#if defined(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PLUGINS) void dummyGetPluginCallback(const std::vector<content::WebPluginInfo>&) { } @@ -197,7 +201,8 @@ void WebEngineContext::destroy() { if (m_devtoolsServer) m_devtoolsServer->stop(); - base::MessagePump::Delegate *delegate = m_runLoop->loop_; + base::MessagePump::Delegate *delegate = + static_cast<base::MessageLoop *>(m_runLoop->delegate_); // Flush the UI message loop before quitting. while (delegate->DoWork()) { } @@ -295,8 +300,10 @@ WebEngineContext::WebEngineContext() appArgs.append(QString::fromLocal8Bit(qgetenv(kChromiumFlagsEnv)).split(' ')); } +#ifdef Q_OS_WIN bool enableWebGLSoftwareRendering = appArgs.removeAll(QStringLiteral("--enable-webgl-software-rendering")); +#endif bool useEmbeddedSwitches = false; #if defined(QTWEBENGINE_EMBEDDED_SWITCHES) @@ -331,7 +338,6 @@ WebEngineContext::WebEngineContext() } parsedCommandLine->AppendSwitch(switches::kEnableThreadedCompositing); - parsedCommandLine->AppendSwitch(switches::kInProcessGPU); // These are currently only default on OS X, and we don't support them: parsedCommandLine->AppendSwitch(switches::kDisableZeroCopy); parsedCommandLine->AppendSwitch(switches::kDisableGpuMemoryBufferCompositorResources); @@ -339,12 +345,17 @@ WebEngineContext::WebEngineContext() // Enabled on OS X and Linux but currently not working. It worked in 5.7 on OS X. parsedCommandLine->AppendSwitch(switches::kDisableGpuMemoryBufferVideoFrames); + // The Mojo local-storage is currently pretty broken and saves in $$PWD/Local\ Storage + parsedCommandLine->AppendSwitch(switches::kDisableMojoLocalStorage); + #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); + // Same problem with select popups. + parsedCommandLine->AppendSwitch(switches::kDisableNativeGpuMemoryBuffers); #endif #if defined(Q_OS_WIN) @@ -358,10 +369,15 @@ WebEngineContext::WebEngineContext() parsedCommandLine->AppendSwitch(switches::kDisableES3GLContext); #endif + // 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. + parsedCommandLine->AppendSwitchASCII(switches::kEnableFeatures, + features::kAllowContentInitiatedDataUrlNavigations.name); + if (useEmbeddedSwitches) { - // Inspired by the Android port's default switches - if (!parsedCommandLine->HasSwitch(switches::kDisableOverlayScrollbar)) - parsedCommandLine->AppendSwitch(switches::kEnableOverlayScrollbar); + parsedCommandLine->AppendSwitchASCII(switches::kEnableFeatures, features::kOverlayScrollbar.name); if (!parsedCommandLine->HasSwitch(switches::kDisablePinch)) parsedCommandLine->AppendSwitch(switches::kEnablePinch); parsedCommandLine->AppendSwitch(switches::kEnableViewport); @@ -445,23 +461,33 @@ WebEngineContext::WebEngineContext() } } } + + if (qt_gl_global_share_context()->format().profile() == QSurfaceFormat::CompatibilityProfile) + parsedCommandLine->AppendSwitch(switches::kCreateDefaultGLContext); } else { qWarning("WebEngineContext used before QtWebEngine::initialize() or OpenGL context creation failed."); } } #endif - if (glType) + if (glType) { parsedCommandLine->AppendSwitchASCII(switches::kUseGL, glType); - else + parsedCommandLine->AppendSwitch(switches::kInProcessGPU); +#ifdef Q_OS_WIN + if (enableWebGLSoftwareRendering) + parsedCommandLine->AppendSwitch(switches::kDisableGpuRasterization); +#endif + } else { parsedCommandLine->AppendSwitch(switches::kDisableGpu); + } content::UtilityProcessHostImpl::RegisterUtilityMainThreadFactory(content::CreateInProcessUtilityThread); content::RenderProcessHostImpl::RegisterRendererMainThreadFactory(content::CreateInProcessRendererThread); - content::GpuProcessHost::RegisterGpuMainThreadFactory(content::CreateInProcessGpuThread); + content::RegisterGpuMainThreadFactory(content::CreateInProcessGpuThread); + + mojo::edk::Init(); content::ContentMainParams contentMainParams(m_mainDelegate.get()); - contentMainParams.setup_signal_handlers = false; #if defined(OS_WIN) sandbox::SandboxInterfaceInfo sandbox_info = {0}; content::InitializeSandboxInfo(&sandbox_info); @@ -481,6 +507,9 @@ WebEngineContext::WebEngineContext() // first gets referenced on the IO thread. MediaCaptureDevicesDispatcher::GetInstance(); + // Initialize WebCacheManager here to ensure its subscription to render process creation events. + web_cache::WebCacheManager::GetInstance(); + base::ThreadRestrictions::SetIOAllowed(true); if (parsedCommandLine->HasSwitch(switches::kExplicitlyAllowedPorts)) { @@ -488,7 +517,7 @@ WebEngineContext::WebEngineContext() net::SetExplicitlyAllowedPorts(allowedPorts); } -#if defined(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PLUGINS) // Creating pepper plugins from the page (which calls PluginService::GetPluginInfoArray) // might fail unless the page queried the list of available plugins at least once // (which ends up calling PluginService::GetPlugins). Since the plugins list can only diff --git a/src/core/web_engine_library_info.cpp b/src/core/web_engine_library_info.cpp index f46f8f425..35b139602 100644 --- a/src/core/web_engine_library_info.cpp +++ b/src/core/web_engine_library_info.cpp @@ -216,26 +216,32 @@ QString dictionariesPath() if (!initialized) { initialized = true; - // First try to find dictionaries near the application. + const QByteArray fromEnv = qgetenv("QTWEBENGINE_DICTIONARIES_PATH"); + if (!fromEnv.isEmpty()) { + // Only search in QTWEBENGINE_DICTIONARIES_PATH if set + candidatePaths << QString::fromLocal8Bit(fromEnv); + } else { + // First try to find dictionaries near the application. #ifdef OS_MACOSX - QString resourcesDictionariesPath = getMainApplicationResourcesPath() - % QDir::separator() % QLatin1String("qtwebengine_dictionaries"); - candidatePaths << resourcesDictionariesPath; + QString resourcesDictionariesPath = getMainApplicationResourcesPath() + % QDir::separator() % QLatin1String("qtwebengine_dictionaries"); + candidatePaths << resourcesDictionariesPath; #endif - QString applicationDictionariesPath = QCoreApplication::applicationDirPath() - % QDir::separator() % QLatin1String("qtwebengine_dictionaries"); - candidatePaths << applicationDictionariesPath; + QString applicationDictionariesPath = QCoreApplication::applicationDirPath() + % QDir::separator() % QLatin1String("qtwebengine_dictionaries"); + candidatePaths << applicationDictionariesPath; - // Then try to find dictionaries near the installed library. + // Then try to find dictionaries near the installed library. #if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD) - QString frameworkDictionariesPath = getResourcesPath(frameworkBundle()) - % QLatin1String("/qtwebengine_dictionaries"); - candidatePaths << frameworkDictionariesPath; + QString frameworkDictionariesPath = getResourcesPath(frameworkBundle()) + % QLatin1String("/qtwebengine_dictionaries"); + candidatePaths << frameworkDictionariesPath; #endif - QString libraryDictionariesPath = QLibraryInfo::location(QLibraryInfo::DataPath) - % QDir::separator() % QLatin1String("qtwebengine_dictionaries"); - candidatePaths << libraryDictionariesPath; + QString libraryDictionariesPath = QLibraryInfo::location(QLibraryInfo::DataPath) + % QDir::separator() % QLatin1String("qtwebengine_dictionaries"); + candidatePaths << libraryDictionariesPath; + } Q_FOREACH (const QString &candidate, candidatePaths) { if (QFileInfo::exists(candidate)) { diff --git a/src/core/web_engine_settings.cpp b/src/core/web_engine_settings.cpp index 39af811e9..19af6b8d5 100644 --- a/src/core/web_engine_settings.cpp +++ b/src/core/web_engine_settings.cpp @@ -83,21 +83,6 @@ private: WebEngineSettings *m_settings; }; -static inline bool isTouchScreenAvailable() { - static bool initialized = false; - static bool touchScreenAvailable = false; - if (!initialized) { - Q_FOREACH (const QTouchDevice *d, QTouchDevice::devices()) { - if (d->type() == QTouchDevice::TouchScreen) { - touchScreenAvailable = true; - break; - } - } - initialized = true; - } - return touchScreenAvailable; -} - static inline bool isTouchEventsAPIEnabled() { static bool initialized = false; static bool touchEventsAPIEnabled = false; @@ -107,21 +92,20 @@ static inline bool isTouchEventsAPIEnabled() { // By default the Touch Events API support (presence of 'ontouchstart' in 'window' object) // will be determined based on the availability of touch screen devices. const std::string touchEventsSwitchValue = - parsedCommandLine->HasSwitch(switches::kTouchEvents) ? - parsedCommandLine->GetSwitchValueASCII(switches::kTouchEvents) : - switches::kTouchEventsAuto; + parsedCommandLine->HasSwitch(switches::kTouchEventFeatureDetection) ? + parsedCommandLine->GetSwitchValueASCII(switches::kTouchEventFeatureDetection) : + switches::kTouchEventFeatureDetectionAuto; - if (touchEventsSwitchValue == switches::kTouchEventsEnabled) + if (touchEventsSwitchValue == switches::kTouchEventFeatureDetectionEnabled) touchEventsAPIEnabled = true; - else if (touchEventsSwitchValue == switches::kTouchEventsAuto) - touchEventsAPIEnabled = isTouchScreenAvailable(); + else if (touchEventsSwitchValue == switches::kTouchEventFeatureDetectionAuto) + touchEventsAPIEnabled = (ui::GetTouchScreensAvailability() == ui::TouchScreensAvailability::ENABLED); initialized = true; } return touchEventsAPIEnabled; } - WebEngineSettings::WebEngineSettings(WebEngineSettings *_parentSettings) : m_adapter(0) , m_batchTimer(new BatchTimer(this)) @@ -228,7 +212,7 @@ QString WebEngineSettings::defaultTextEncoding() const return m_defaultEncoding.isEmpty()? parentSettings->defaultTextEncoding() : m_defaultEncoding; } -void WebEngineSettings::initDefaults(bool offTheRecord) +void WebEngineSettings::initDefaults() { if (s_defaultAttributes.isEmpty()) { // Initialize the default settings. @@ -247,6 +231,7 @@ void WebEngineSettings::initDefaults(bool offTheRecord) s_defaultAttributes.insert(PluginsEnabled, false); s_defaultAttributes.insert(FullScreenSupportEnabled, false); s_defaultAttributes.insert(ScreenCaptureEnabled, false); + s_defaultAttributes.insert(ShowScrollBars, true); // The following defaults matches logic in render_view_host_impl.cc // But first we must ensure the WebContext has been initialized QtWebEngineCore::WebEngineContext::current(); @@ -263,13 +248,12 @@ void WebEngineSettings::initDefaults(bool offTheRecord) s_defaultAttributes.insert(Accelerated2dCanvasEnabled, accelerated2dCanvas); s_defaultAttributes.insert(AutoLoadIconsForPage, true); s_defaultAttributes.insert(TouchIconsEnabled, false); - s_defaultAttributes.insert(FocusOnNavigationEnabled, true); + s_defaultAttributes.insert(FocusOnNavigationEnabled, false); s_defaultAttributes.insert(PrintElementBackgrounds, true); s_defaultAttributes.insert(AllowRunningInsecureContent, allowRunningInsecureContent); s_defaultAttributes.insert(AllowGeolocationOnInsecureOrigins, false); + s_defaultAttributes.insert(AllowWindowActivationFromJavaScript, false); } - if (offTheRecord) - m_attributes.insert(LocalStorageEnabled, false); if (s_defaultFontFamilies.isEmpty()) { // Default fonts @@ -322,8 +306,7 @@ void WebEngineSettings::doApply() void WebEngineSettings::applySettingsToWebPreferences(content::WebPreferences *prefs) { // Override for now - prefs->touch_enabled = isTouchEventsAPIEnabled(); - prefs->device_supports_touch = isTouchScreenAvailable(); + prefs->touch_event_feature_detection_enabled = isTouchEventsAPIEnabled(); if (prefs->viewport_enabled) { // We need to enable the viewport options together as it doesn't really work // to enable them separately. With viewport-enabled we match Android defaults. @@ -334,7 +317,6 @@ void WebEngineSettings::applySettingsToWebPreferences(content::WebPreferences *p // Attributes mapping. prefs->loads_images_automatically = testAttribute(AutoLoadImages); prefs->javascript_enabled = testAttribute(JavascriptEnabled); - prefs->javascript_can_open_windows_automatically = testAttribute(JavascriptCanOpenWindows); prefs->javascript_can_access_clipboard = testAttribute(JavascriptCanAccessClipboard); prefs->tabs_to_links = testAttribute(LinksIncludedInFocusChain); prefs->local_storage_enabled = testAttribute(LocalStorageEnabled); @@ -353,6 +335,7 @@ void WebEngineSettings::applySettingsToWebPreferences(content::WebPreferences *p prefs->should_print_backgrounds = testAttribute(PrintElementBackgrounds); prefs->allow_running_insecure_content = testAttribute(AllowRunningInsecureContent); prefs->allow_geolocation_on_insecure_origins = testAttribute(AllowGeolocationOnInsecureOrigins); + prefs->hide_scrollbars = !testAttribute(ShowScrollBars); // Fonts settings. prefs->standard_font_family_map[content::kCommonScript] = toString16(fontFamily(StandardFont)); @@ -377,6 +360,11 @@ void WebEngineSettings::scheduleApplyRecursively() } } +bool WebEngineSettings::getJavaScriptCanOpenWindowsAutomatically() +{ + return testAttribute(JavascriptCanOpenWindows); +} + void WebEngineSettings::setParentSettings(WebEngineSettings *_parentSettings) { if (parentSettings) diff --git a/src/core/web_engine_settings.h b/src/core/web_engine_settings.h index 4b0ce7b39..18963344a 100644 --- a/src/core/web_engine_settings.h +++ b/src/core/web_engine_settings.h @@ -83,7 +83,9 @@ public: FocusOnNavigationEnabled, PrintElementBackgrounds, AllowRunningInsecureContent, - AllowGeolocationOnInsecureOrigins + AllowGeolocationOnInsecureOrigins, + AllowWindowActivationFromJavaScript, + ShowScrollBars }; // Must match the values from the public API in qwebenginesettings.h. @@ -127,11 +129,13 @@ public: void setDefaultTextEncoding(const QString &encoding); QString defaultTextEncoding() const; - void initDefaults(bool offTheRecord = false); + void initDefaults(); void scheduleApply(); void scheduleApplyRecursively(); + bool getJavaScriptCanOpenWindowsAutomatically(); + private: void doApply(); void applySettingsToWebPreferences(content::WebPreferences *); diff --git a/src/core/web_event_factory.cpp b/src/core/web_event_factory.cpp index 7245e29e6..359eb5a58 100644 --- a/src/core/web_event_factory.cpp +++ b/src/core/web_event_factory.cpp @@ -72,12 +72,12 @@ #include <QCoreApplication> #include <QElapsedTimer> +#include <QGuiApplication> #include <QKeyEvent> #include <QMouseEvent> +#include <QStyleHints> #include <QWheelEvent> -static const int wheelScrollLines = 3; // FIXME: Still not available in QStyleHints in 5.1 - using namespace blink; static int windowsKeyCodeForKeyEvent(unsigned int keycode, bool isKeypad) @@ -902,11 +902,11 @@ static ui::DomKey getDomKeyFromQKeyEvent(QKeyEvent *ev) // Audio Keys case Qt::Key_BassDown: - return ui::DomKey::AUDIO_BASS_DOWN; + return ui::DomKey::AUDIO_BASS_BOOST_DOWN; case Qt::Key_BassBoost: return ui::DomKey::AUDIO_BASS_BOOST_TOGGLE; case Qt::Key_BassUp: - return ui::DomKey::AUDIO_BASS_UP; + return ui::DomKey::AUDIO_BASS_BOOST_UP; case Qt::Key_TrebleDown: return ui::DomKey::AUDIO_TREBLE_DOWN; case Qt::Key_TrebleUp: @@ -1038,25 +1038,25 @@ static inline double currentTimeForEvent(const QEvent *event) static WebMouseEvent::Button mouseButtonForEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) - return WebMouseEvent::Button::Left; + return WebMouseEvent::Button::kLeft; else if (event->button() == Qt::RightButton) - return WebMouseEvent::Button::Right; + return WebMouseEvent::Button::kRight; else if (event->button() == Qt::MidButton) - return WebMouseEvent::Button::Middle; + return WebMouseEvent::Button::kMiddle; if (event->type() != QEvent::MouseMove) - return WebMouseEvent::Button::NoButton; + return WebMouseEvent::Button::kNoButton; // This is technically wrong, mouse move should always have ButtonNone, // but it is consistent with aura and selection code depends on it: if (event->buttons() & Qt::LeftButton) - return WebMouseEvent::Button::Left; + return WebMouseEvent::Button::kLeft; else if (event->buttons() & Qt::RightButton) - return WebMouseEvent::Button::Right; + return WebMouseEvent::Button::kRight; else if (event->buttons() & Qt::MidButton) - return WebMouseEvent::Button::Middle; + return WebMouseEvent::Button::kMiddle; - return WebMouseEvent::Button::NoButton; + return WebMouseEvent::Button::kNoButton; } template <typename T> @@ -1064,11 +1064,11 @@ static unsigned mouseButtonsModifiersForEvent(const T* event) { unsigned ret = 0; if (event->buttons() & Qt::LeftButton) - ret |= WebInputEvent::LeftButtonDown; + ret |= WebInputEvent::kLeftButtonDown; if (event->buttons() & Qt::RightButton) - ret |= WebInputEvent::RightButtonDown; + ret |= WebInputEvent::kRightButtonDown; if (event->buttons() & Qt::MidButton) - ret |= WebInputEvent::MiddleButtonDown; + ret |= WebInputEvent::kMiddleButtonDown; return ret; } @@ -1078,19 +1078,19 @@ static inline WebInputEvent::Modifiers modifierForKeyCode(int key) { switch (key) { case Qt::Key_Shift: - return WebInputEvent::ShiftKey; + return WebInputEvent::kShiftKey; case Qt::Key_Alt: - return WebInputEvent::AltKey; + return WebInputEvent::kAltKey; #if defined(Q_OS_OSX) case Qt::Key_Control: - return (!qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) ? WebInputEvent::MetaKey : WebInputEvent::ControlKey; + return (!qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) ? WebInputEvent::kMetaKey : WebInputEvent::kControlKey; case Qt::Key_Meta: - return (!qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) ? WebInputEvent::ControlKey : WebInputEvent::MetaKey; + return (!qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) ? WebInputEvent::kControlKey : WebInputEvent::kMetaKey; #else case Qt::Key_Control: - return WebInputEvent::ControlKey; + return WebInputEvent::kControlKey; case Qt::Key_Meta: - return WebInputEvent::MetaKey; + return WebInputEvent::kMetaKey; #endif default: return static_cast<WebInputEvent::Modifiers>(0); @@ -1104,24 +1104,24 @@ static inline WebInputEvent::Modifiers modifiersForEvent(const QInputEvent* even #if defined(Q_OS_OSX) if (!qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { if (modifiers & Qt::ControlModifier) - result |= WebInputEvent::MetaKey; + result |= WebInputEvent::kMetaKey; if (modifiers & Qt::MetaModifier) - result |= WebInputEvent::ControlKey; + result |= WebInputEvent::kControlKey; } else #endif { if (modifiers & Qt::ControlModifier) - result |= WebInputEvent::ControlKey; + result |= WebInputEvent::kControlKey; if (modifiers & Qt::MetaModifier) - result |= WebInputEvent::MetaKey; + result |= WebInputEvent::kMetaKey; } if (modifiers & Qt::ShiftModifier) - result |= WebInputEvent::ShiftKey; + result |= WebInputEvent::kShiftKey; if (modifiers & Qt::AltModifier) - result |= WebInputEvent::AltKey; + result |= WebInputEvent::kAltKey; if (modifiers & Qt::KeypadModifier) - result |= WebInputEvent::IsKeyPad; + result |= WebInputEvent::kIsKeyPad; switch (event->type()) { case QEvent::MouseButtonPress: @@ -1136,7 +1136,7 @@ static inline WebInputEvent::Modifiers modifiersForEvent(const QInputEvent* even case QEvent::KeyRelease: { const QKeyEvent *keyEvent = static_cast<const QKeyEvent*>(event); if (keyEvent->isAutoRepeat()) - result |= WebInputEvent::IsAutoRepeat; + result |= WebInputEvent::kIsAutoRepeat; result |= modifierForKeyCode(keyEvent->key()); } default: @@ -1150,52 +1150,50 @@ static WebInputEvent::Type webEventTypeForEvent(const QEvent* event) { switch (event->type()) { case QEvent::MouseButtonPress: - return WebInputEvent::MouseDown; + return WebInputEvent::kMouseDown; case QEvent::MouseButtonRelease: - return WebInputEvent::MouseUp; + return WebInputEvent::kMouseUp; case QEvent::Enter: - return WebInputEvent::MouseEnter; + return WebInputEvent::kMouseEnter; case QEvent::Leave: - return WebInputEvent::MouseLeave; + return WebInputEvent::kMouseLeave; case QEvent::MouseMove: - return WebInputEvent::MouseMove; + return WebInputEvent::kMouseMove; case QEvent::Wheel: - return WebInputEvent::MouseWheel; + return WebInputEvent::kMouseWheel; case QEvent::KeyPress: - return WebInputEvent::RawKeyDown; + return WebInputEvent::kRawKeyDown; case QEvent::KeyRelease: - return WebInputEvent::KeyUp; + return WebInputEvent::kKeyUp; case QEvent::HoverMove: - return WebInputEvent::MouseMove; + return WebInputEvent::kMouseMove; case QEvent::TouchBegin: - return WebInputEvent::TouchStart; + return WebInputEvent::kTouchStart; case QEvent::TouchUpdate: - return WebInputEvent::TouchMove; + return WebInputEvent::kTouchMove; case QEvent::TouchEnd: - return WebInputEvent::TouchEnd; + return WebInputEvent::kTouchEnd; case QEvent::TouchCancel: - return WebInputEvent::TouchCancel; + return WebInputEvent::kTouchCancel; default: Q_ASSERT(false); - return WebInputEvent::MouseMove; + return WebInputEvent::kMouseMove; } } WebMouseEvent WebEventFactory::toWebMouseEvent(QMouseEvent *ev, double dpiScale) { - WebMouseEvent webKitEvent; - webKitEvent.timeStampSeconds = currentTimeForEvent(ev); - webKitEvent.button = mouseButtonForEvent(ev); - webKitEvent.modifiers = modifiersForEvent(ev); + WebMouseEvent webKitEvent(webEventTypeForEvent(ev), + ev->x() / dpiScale, + ev->y() / dpiScale, + ev->globalX(), + ev->globalY(), + modifiersForEvent(ev), + currentTimeForEvent(ev)); - webKitEvent.x = webKitEvent.windowX = ev->x() / dpiScale; - webKitEvent.y = webKitEvent.windowY = ev->y() / dpiScale; - webKitEvent.globalX = ev->globalX(); - webKitEvent.globalY = ev->globalY(); - - webKitEvent.type = webEventTypeForEvent(ev); - webKitEvent.clickCount = 0; - webKitEvent.pointerType = WebPointerProperties::PointerType::Mouse; + webKitEvent.button = mouseButtonForEvent(ev); + webKitEvent.click_count = 0; + webKitEvent.pointer_type = WebPointerProperties::PointerType::kMouse; return webKitEvent; } @@ -1203,16 +1201,15 @@ WebMouseEvent WebEventFactory::toWebMouseEvent(QMouseEvent *ev, double dpiScale) WebMouseEvent WebEventFactory::toWebMouseEvent(QHoverEvent *ev, double dpiScale) { WebMouseEvent webKitEvent; - webKitEvent.timeStampSeconds = currentTimeForEvent(ev); - webKitEvent.modifiers = modifiersForEvent(ev); + webKitEvent.SetTimeStampSeconds(currentTimeForEvent(ev)); + webKitEvent.SetModifiers(modifiersForEvent(ev)); + webKitEvent.SetType(webEventTypeForEvent(ev)); - webKitEvent.x = webKitEvent.windowX = ev->pos().x() / dpiScale; - webKitEvent.y = webKitEvent.windowY = ev->pos().y() / dpiScale; - webKitEvent.movementX = ev->pos().x() - ev->oldPos().x(); - webKitEvent.movementY = ev->pos().y() - ev->oldPos().y(); - webKitEvent.pointerType = WebPointerProperties::PointerType::Mouse; + webKitEvent.SetPositionInWidget(ev->pos().x() / dpiScale, ev->pos().y() / dpiScale); + webKitEvent.movement_x = ev->pos().x() - ev->oldPos().x(); + webKitEvent.movement_y = ev->pos().y() - ev->oldPos().y(); + webKitEvent.pointer_type = WebPointerProperties::PointerType::kMouse; - webKitEvent.type = webEventTypeForEvent(ev); return webKitEvent; } @@ -1221,8 +1218,8 @@ WebMouseEvent WebEventFactory::toWebMouseEvent(QEvent *ev) Q_ASSERT(ev->type() == QEvent::Leave || ev->type() == QEvent::HoverLeave); WebMouseEvent webKitEvent; - webKitEvent.timeStampSeconds = currentTimeForEvent(ev); - webKitEvent.type = WebInputEvent::MouseLeave; + webKitEvent.SetTimeStampSeconds(currentTimeForEvent(ev)); + webKitEvent.SetType(WebInputEvent::kMouseLeave); return webKitEvent; } @@ -1230,26 +1227,26 @@ WebMouseEvent WebEventFactory::toWebMouseEvent(QEvent *ev) WebGestureEvent WebEventFactory::toWebGestureEvent(QNativeGestureEvent *ev, double dpiScale) { WebGestureEvent webKitEvent; - webKitEvent.timeStampSeconds = currentTimeForEvent(ev); - webKitEvent.modifiers = modifiersForEvent(ev); + webKitEvent.SetTimeStampSeconds(currentTimeForEvent(ev)); + webKitEvent.SetModifiers(modifiersForEvent(ev)); webKitEvent.x = static_cast<int>(ev->localPos().x() / dpiScale); webKitEvent.y = static_cast<int>(ev->localPos().y() / dpiScale); - webKitEvent.globalX = static_cast<int>(ev->screenPos().x() / dpiScale); - webKitEvent.globalY = static_cast<int>(ev->screenPos().y() / dpiScale); + webKitEvent.global_x = static_cast<int>(ev->screenPos().x() / dpiScale); + webKitEvent.global_y = static_cast<int>(ev->screenPos().y() / dpiScale); - webKitEvent.sourceDevice = blink::WebGestureDeviceTouchpad; + webKitEvent.source_device = blink::kWebGestureDeviceTouchpad; Qt::NativeGestureType gestureType = ev->gestureType(); switch (gestureType) { case Qt::ZoomNativeGesture: - webKitEvent.type = WebInputEvent::GesturePinchUpdate; - webKitEvent.data.pinchUpdate.scale = static_cast<float>(ev->value() + 1.0); + webKitEvent.SetType(WebInputEvent::kGesturePinchUpdate); + webKitEvent.data.pinch_update.scale = static_cast<float>(ev->value() + 1.0); break; case Qt::SmartZoomNativeGesture: - webKitEvent.type = WebInputEvent::GestureDoubleTap; - webKitEvent.data.tap.tapCount = 1; + webKitEvent.SetType(WebInputEvent::kGestureDoubleTap); + webKitEvent.data.tap.tap_count = 1; break; case Qt::BeginNativeGesture: case Qt::EndNativeGesture: @@ -1257,7 +1254,7 @@ WebGestureEvent WebEventFactory::toWebGestureEvent(QNativeGestureEvent *ev, doub case Qt::PanNativeGesture: case Qt::SwipeNativeGesture: // Not implemented by Chromium for now. - webKitEvent.type = blink::WebInputEvent::Undefined; + webKitEvent.SetType(blink::WebInputEvent::kUndefined); break; } @@ -1265,62 +1262,164 @@ WebGestureEvent WebEventFactory::toWebGestureEvent(QNativeGestureEvent *ev, doub } #endif -blink::WebMouseWheelEvent WebEventFactory::toWebWheelEvent(QWheelEvent *ev, double dpiScale) +static void setBlinkWheelEventDelta(blink::WebMouseWheelEvent &webEvent) { - WebMouseWheelEvent webEvent; - webEvent.type = webEventTypeForEvent(ev); - webEvent.deltaX = 0; - webEvent.deltaY = 0; - webEvent.wheelTicksX = 0; - webEvent.wheelTicksY = 0; - webEvent.modifiers = modifiersForEvent(ev); - webEvent.timeStampSeconds = currentTimeForEvent(ev); - - webEvent.wheelTicksX = static_cast<float>(ev->angleDelta().x()) / QWheelEvent::DefaultDeltasPerStep; - webEvent.wheelTicksY = static_cast<float>(ev->angleDelta().y()) / QWheelEvent::DefaultDeltasPerStep; - // We can't use the device specific QWheelEvent::pixelDelta(), so we calculate // a pixel delta based on ticks and scroll per line. static const float cDefaultQtScrollStep = 20.f; - webEvent.deltaX = webEvent.wheelTicksX * wheelScrollLines * cDefaultQtScrollStep; - webEvent.deltaY = webEvent.wheelTicksY * wheelScrollLines * cDefaultQtScrollStep; +#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)) + static const int wheelScrollLines = QGuiApplication::styleHints()->wheelScrollLines(); +#else + static const int wheelScrollLines = 3; +#endif + webEvent.delta_x = webEvent.wheel_ticks_x * wheelScrollLines * cDefaultQtScrollStep; + webEvent.delta_y = webEvent.wheel_ticks_y * wheelScrollLines * cDefaultQtScrollStep; +} + + +blink::WebMouseWheelEvent WebEventFactory::toWebWheelEvent(QWheelEvent *ev, double dpiScale) +{ + WebMouseWheelEvent webEvent; + webEvent.SetType(webEventTypeForEvent(ev)); + webEvent.SetModifiers(modifiersForEvent(ev)); + webEvent.SetTimeStampSeconds(currentTimeForEvent(ev)); + webEvent.SetPositionInWidget(ev->x() / dpiScale, ev->y() / dpiScale); + webEvent.SetPositionInScreen(ev->globalX(), ev->globalY()); + + webEvent.wheel_ticks_x = static_cast<float>(ev->angleDelta().x()) / QWheelEvent::DefaultDeltasPerStep; + webEvent.wheel_ticks_y = static_cast<float>(ev->angleDelta().y()) / QWheelEvent::DefaultDeltasPerStep; + setBlinkWheelEventDelta(webEvent); - webEvent.x = webEvent.windowX = ev->x() / dpiScale; - webEvent.y = webEvent.windowY = ev->y() / dpiScale; - webEvent.globalX = ev->globalX(); - webEvent.globalY = ev->globalY(); return webEvent; } +bool WebEventFactory::coalesceWebWheelEvent(blink::WebMouseWheelEvent &webEvent, QWheelEvent *ev, double dpiScale) +{ + if (webEventTypeForEvent(ev) != webEvent.GetType()) + return false; + if (modifiersForEvent(ev) != webEvent.GetModifiers()) + return false; + + webEvent.SetTimeStampSeconds(currentTimeForEvent(ev)); + webEvent.SetPositionInWidget(ev->x() / dpiScale, ev->y() / dpiScale); + webEvent.SetPositionInScreen(ev->globalX(), ev->globalY()); + + webEvent.wheel_ticks_x += static_cast<float>(ev->angleDelta().x()) / QWheelEvent::DefaultDeltasPerStep; + webEvent.wheel_ticks_y += static_cast<float>(ev->angleDelta().y()) / QWheelEvent::DefaultDeltasPerStep; + setBlinkWheelEventDelta(webEvent); + + return true; +} + content::NativeWebKeyboardEvent WebEventFactory::toWebKeyboardEvent(QKeyEvent *ev) { content::NativeWebKeyboardEvent webKitEvent(reinterpret_cast<gfx::NativeEvent>(ev)); - webKitEvent.timeStampSeconds = currentTimeForEvent(ev); - webKitEvent.modifiers = modifiersForEvent(ev); - webKitEvent.type = webEventTypeForEvent(ev); + webKitEvent.SetTimeStampSeconds(currentTimeForEvent(ev)); + webKitEvent.SetModifiers(modifiersForEvent(ev)); + webKitEvent.SetType(webEventTypeForEvent(ev)); - webKitEvent.nativeKeyCode = ev->nativeVirtualKey(); - webKitEvent.windowsKeyCode = windowsKeyCodeForKeyEvent(ev->key(), ev->modifiers() & Qt::KeypadModifier); - webKitEvent.domKey = getDomKeyFromQKeyEvent(ev); + webKitEvent.native_key_code = ev->nativeVirtualKey(); + webKitEvent.windows_key_code = windowsKeyCodeForKeyEvent(ev->key(), ev->modifiers() & Qt::KeypadModifier); + webKitEvent.dom_key = getDomKeyFromQKeyEvent(ev); ui::DomCode domCode = ui::DomCode::NONE; int scanCode = ev->nativeScanCode(); if (scanCode) domCode = ui::KeycodeConverter::NativeKeycodeToDomCode(scanCode); - webKitEvent.domCode = static_cast<int>(domCode); + webKitEvent.dom_code = static_cast<int>(domCode); const ushort* text = ev->text().utf16(); memcpy(&webKitEvent.text, text, std::min(sizeof(webKitEvent.text), size_t(ev->text().length() * 2))); - memcpy(&webKitEvent.unmodifiedText, text, std::min(sizeof(webKitEvent.unmodifiedText), size_t(ev->text().length() * 2))); + memcpy(&webKitEvent.unmodified_text, text, std::min(sizeof(webKitEvent.unmodified_text), size_t(ev->text().length() * 2))); - if (webKitEvent.windowsKeyCode == VK_RETURN) { + if (webKitEvent.windows_key_code == VK_RETURN) { // This is the same behavior as GTK: // We need to treat the enter key as a key press of character \r. This // is apparently just how webkit handles it and what it expects. - webKitEvent.unmodifiedText[0] = '\r'; - webKitEvent.text[0] = webKitEvent.unmodifiedText[0]; + webKitEvent.unmodified_text[0] = '\r'; + webKitEvent.text[0] = webKitEvent.unmodified_text[0]; } return webKitEvent; } + +bool WebEventFactory::getEditCommand(QKeyEvent *event, std::string *editCommand) +{ + // Assign Qt standard key bindings to blink editor commands. Editor command names + // come from chromium/third_party/WebKit/Source/editing/commands/EditorCommandNames.h + static struct { + QKeySequence::StandardKey standardKey; + std::string name; + } editCommands[] = { + { QKeySequence::Delete, "Delete" }, + { QKeySequence::Cut, "Cut" }, + { QKeySequence::Copy, "Copy" }, + { QKeySequence::Paste, "Paste" }, + { QKeySequence::Undo, "Undo" }, + { QKeySequence::Redo, "Redo" }, + { QKeySequence::SelectAll, "SelectAll" }, + { QKeySequence::Bold, "Bold" }, + { QKeySequence::Italic, "Italic" }, + { QKeySequence::Underline, "Underline" }, + + { QKeySequence::MoveToNextChar, "MoveRight" }, + { QKeySequence::MoveToPreviousChar, "MoveLeft" }, + { QKeySequence::MoveToNextWord, "MoveWordForward" }, + { QKeySequence::MoveToPreviousWord, "MoveWordBackward" }, + { QKeySequence::MoveToNextLine, "MoveDown" }, + { QKeySequence::MoveToPreviousLine, "MoveUp" }, + { QKeySequence::MoveToNextPage, "MovePageDown" }, + { QKeySequence::MoveToPreviousPage, "MovePageUp" }, + { QKeySequence::MoveToStartOfLine, "MoveToBeginningOfLine" }, + { QKeySequence::MoveToEndOfLine, "MoveToEndOfLine" }, + { QKeySequence::MoveToStartOfBlock, "MoveToBeginningOfParagraph" }, + { QKeySequence::MoveToEndOfBlock, "MoveToEndOfParagraph" }, + { QKeySequence::MoveToStartOfDocument, "MoveToBeginningOfDocument" }, + { QKeySequence::MoveToEndOfDocument, "MoveToEndOfDocument" }, + + { QKeySequence::SelectNextChar, "MoveRightAndModifySelection" }, + { QKeySequence::SelectPreviousChar, "MoveLeftAndModifySelection" }, + { QKeySequence::SelectNextWord, "MoveWordForwardAndModifySelection" }, + { QKeySequence::SelectPreviousWord, "MoveWordBackwardAndModifySelection" }, + { QKeySequence::SelectNextLine, "MoveDownAndModifySelection" }, + { QKeySequence::SelectPreviousLine, "MoveUpAndModifySelection" }, + { QKeySequence::SelectNextPage, "MovePageDownAndModifySelection" }, + { QKeySequence::SelectPreviousPage, "MovePageUpAndModifySelection" }, + { QKeySequence::SelectStartOfLine, "MoveToBeginningOfLineAndModifySelection" }, + { QKeySequence::SelectEndOfLine, "MoveToEndOfLineAndModifySelection" }, + { QKeySequence::SelectStartOfBlock, "MoveToBeginningOfParagraphAndModifySelection" }, + { QKeySequence::SelectEndOfBlock, "MoveToEndOfParagraphAndModifySelection" }, + { QKeySequence::SelectStartOfDocument, "MoveToBeginningOfDocumentAndModifySelection" }, + { QKeySequence::SelectEndOfDocument, "MoveToEndOfDocumentAndModifySelection" }, + + { QKeySequence::DeleteStartOfWord, "DeleteWordBackward" }, + { QKeySequence::DeleteEndOfWord, "DeleteWordForward" }, + { QKeySequence::DeleteEndOfLine, "DeleteToEndOfLine" }, + { QKeySequence::Deselect, "Unselect" }, + { QKeySequence::Backspace, "BackwardDelete" }, + + { QKeySequence::UnknownKey, "" } + }; + + for (int i = 0; editCommands[i].standardKey != QKeySequence::UnknownKey; ++i) { + if (event == editCommands[i].standardKey) { + *editCommand = editCommands[i].name; + return true; + } + } + +#ifdef Q_OS_MACOS + Qt::KeyboardModifier cmdKey = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta) ? + Qt::MetaModifier : + Qt::ControlModifier; + if ((event->modifiers() & ~Qt::ShiftModifier) == cmdKey) { + if (event->key() == Qt::Key_Backspace) { + *editCommand = "DeleteToBeginningOfLine"; + return true; + } + } +#endif + + return false; +} diff --git a/src/core/web_event_factory.h b/src/core/web_event_factory.h index b28710d66..5b8f08968 100644 --- a/src/core/web_event_factory.h +++ b/src/core/web_event_factory.h @@ -41,10 +41,11 @@ #define WEB_EVENT_FACTORY_H #include "content/public/browser/native_web_keyboard_event.h" -#include "third_party/WebKit/public/platform/WebInputEvent.h" #ifndef QT_NO_GESTURES #include "third_party/WebKit/public/platform/WebGestureEvent.h" #endif +#include "third_party/WebKit/public/platform/WebMouseEvent.h" +#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h" #include <QtGlobal> @@ -69,7 +70,9 @@ public: static blink::WebGestureEvent toWebGestureEvent(QNativeGestureEvent *, double dpiScale); #endif static blink::WebMouseWheelEvent toWebWheelEvent(QWheelEvent*, double dpiScale); + static bool coalesceWebWheelEvent(blink::WebMouseWheelEvent &, QWheelEvent*, double dpiScale); static content::NativeWebKeyboardEvent toWebKeyboardEvent(QKeyEvent*); + static bool getEditCommand(QKeyEvent *event, std::string *editCommand); }; |