diff options
-rw-r--r-- | lib/quick/qquickwebengineview.cpp | 10 | ||||
-rw-r--r-- | lib/quick/qquickwebengineview_p_p.h | 1 | ||||
-rw-r--r-- | lib/render_widget_host_view_qt.cpp | 22 | ||||
-rw-r--r-- | lib/render_widget_host_view_qt.h | 9 | ||||
-rw-r--r-- | lib/web_contents_adapter.cpp | 32 | ||||
-rw-r--r-- | lib/web_contents_adapter.h | 4 | ||||
-rw-r--r-- | lib/web_contents_adapter_client.h | 17 | ||||
-rw-r--r-- | lib/web_contents_delegate_qt.cpp | 18 | ||||
-rw-r--r-- | lib/web_contents_delegate_qt.h | 1 | ||||
-rw-r--r-- | lib/web_contents_view_qt.cpp | 37 | ||||
-rw-r--r-- | lib/web_contents_view_qt.h | 16 | ||||
-rw-r--r-- | lib/widgets/Api/qwebenginepage.cpp | 25 | ||||
-rw-r--r-- | lib/widgets/Api/qwebenginepage.h | 2 | ||||
-rw-r--r-- | lib/widgets/Api/qwebenginepage_p.h | 1 | ||||
-rw-r--r-- | lib/widgets/Api/qwebengineview.cpp | 6 | ||||
-rw-r--r-- | lib/widgets/Api/qwebengineview.h | 4 | ||||
-rw-r--r-- | tests/widgets/qwebenginepage/tst_qwebenginepage.cpp | 4 |
17 files changed, 174 insertions, 35 deletions
diff --git a/lib/quick/qquickwebengineview.cpp b/lib/quick/qquickwebengineview.cpp index 80ddc287f..fa68660ae 100644 --- a/lib/quick/qquickwebengineview.cpp +++ b/lib/quick/qquickwebengineview.cpp @@ -49,8 +49,9 @@ QQuickWebEngineViewPrivate::QQuickWebEngineViewPrivate() - : adapter(new WebContentsAdapter(this)) + : adapter(new WebContentsAdapter) { + adapter->initialize(this); } RenderWidgetHostViewQtDelegate *QQuickWebEngineViewPrivate::CreateRenderWidgetHostViewQtDelegate() @@ -97,6 +98,13 @@ void QQuickWebEngineViewPrivate::focusContainer() q->forceActiveFocus(); } +void QQuickWebEngineViewPrivate::adoptNewWindow(WebContentsAdapter *newWebContents, WindowOpenDisposition disposition) +{ + Q_UNUSED(newWebContents); + Q_UNUSED(disposition); + Q_UNREACHABLE(); +} + QQuickWebEngineView::QQuickWebEngineView(QQuickItem *parent) : QQuickItem(*(new QQuickWebEngineViewPrivate), parent) { diff --git a/lib/quick/qquickwebengineview_p_p.h b/lib/quick/qquickwebengineview_p_p.h index 3d74f60de..f2475954d 100644 --- a/lib/quick/qquickwebengineview_p_p.h +++ b/lib/quick/qquickwebengineview_p_p.h @@ -64,6 +64,7 @@ public: virtual QRectF viewportRect() const Q_DECL_OVERRIDE; virtual void loadFinished(bool success) Q_DECL_OVERRIDE; virtual void focusContainer() Q_DECL_OVERRIDE; + virtual void adoptNewWindow(WebContentsAdapter *newWebContents, WindowOpenDisposition disposition) Q_DECL_OVERRIDE; QExplicitlySharedDataPointer<WebContentsAdapter> adapter; friend class RenderWidgetHostViewQtDelegateQuick; diff --git a/lib/render_widget_host_view_qt.cpp b/lib/render_widget_host_view_qt.cpp index ce9f4a5b5..bf35d108a 100644 --- a/lib/render_widget_host_view_qt.cpp +++ b/lib/render_widget_host_view_qt.cpp @@ -98,6 +98,8 @@ static void UpdateWebTouchEventAfterDispatch(WebKit::WebTouchEvent* event, WebKi RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost* widget) : m_host(content::RenderWidgetHostImpl::From(widget)) , m_gestureRecognizer(ui::GestureRecognizer::Create(this)) + , m_adapterClient(0) + , m_initPending(false) { m_host->SetView(this); } @@ -106,12 +108,21 @@ RenderWidgetHostViewQt::~RenderWidgetHostViewQt() { } -void RenderWidgetHostViewQt::SetDelegate(RenderWidgetHostViewQtDelegate* delegate) +void RenderWidgetHostViewQt::setDelegate(RenderWidgetHostViewQtDelegate* delegate) { m_delegate.reset(delegate); delegate->setView(this); } +void RenderWidgetHostViewQt::setAdapterClient(WebContentsAdapterClient *adapterClient) +{ + Q_ASSERT(!m_adapterClient); + + m_adapterClient = adapterClient; + if (m_initPending) + InitAsChild(0); +} + bool RenderWidgetHostViewQt::handleEvent(QEvent* event) { switch(event->type()) { @@ -159,9 +170,14 @@ content::BackingStore *RenderWidgetHostViewQt::AllocBackingStore(const gfx::Size return new BackingStoreQt(m_host, size, new QWindow); } -void RenderWidgetHostViewQt::InitAsChild(gfx::NativeView parent_view) +void RenderWidgetHostViewQt::InitAsChild(gfx::NativeView) { - m_delegate->initAsChild(reinterpret_cast<WebContentsAdapterClient*>(parent_view)); + if (!m_adapterClient) { + m_initPending = true; + return; + } + m_initPending = false; + m_delegate->initAsChild(m_adapterClient); } void RenderWidgetHostViewQt::InitAsPopup(content::RenderWidgetHostView*, const gfx::Rect&) diff --git a/lib/render_widget_host_view_qt.h b/lib/render_widget_host_view_qt.h index d580a00ca..7a9546a48 100644 --- a/lib/render_widget_host_view_qt.h +++ b/lib/render_widget_host_view_qt.h @@ -60,6 +60,7 @@ class QMouseEvent; class QTouchEvent; class QWheelEvent; class RenderWidgetHostViewQtDelegate; +class WebContentsAdapterClient; class RenderWidgetHostViewQt : public content::RenderWidgetHostViewBase @@ -70,13 +71,14 @@ public: RenderWidgetHostViewQt(content::RenderWidgetHost* widget); ~RenderWidgetHostViewQt(); - void SetDelegate(RenderWidgetHostViewQtDelegate* delegate); + void setDelegate(RenderWidgetHostViewQtDelegate *delegate); + void setAdapterClient(WebContentsAdapterClient *adapterClient); bool handleEvent(QEvent* event); BackingStoreQt* GetBackingStore(); virtual content::BackingStore *AllocBackingStore(const gfx::Size &size); - virtual void InitAsChild(gfx::NativeView parent_view); + virtual void InitAsChild(gfx::NativeView); virtual void InitAsPopup(content::RenderWidgetHostView*, const gfx::Rect&); virtual void InitAsFullscreen(content::RenderWidgetHostView*); virtual content::RenderWidgetHost* GetRenderWidgetHost() const; @@ -170,6 +172,9 @@ private: QMap<int, int> m_touchIdMapping; WebKit::WebTouchEvent m_accumTouchEvent; scoped_ptr<RenderWidgetHostViewQtDelegate> m_delegate; + WebContentsAdapterClient *m_adapterClient; + + bool m_initPending; }; #endif // RENDER_WIDGET_HOST_VIEW_QT_H diff --git a/lib/web_contents_adapter.cpp b/lib/web_contents_adapter.cpp index efcda76f3..7fa180e70 100644 --- a/lib/web_contents_adapter.cpp +++ b/lib/web_contents_adapter.cpp @@ -73,17 +73,31 @@ WebContentsAdapterPrivate::WebContentsAdapterPrivate() { } -WebContentsAdapter::WebContentsAdapter(WebContentsAdapterClient *adapterClient) +WebContentsAdapter::WebContentsAdapter(content::WebContents *webContents) : d_ptr(new WebContentsAdapterPrivate) { Q_D(WebContentsAdapter); + d->webContents.reset(webContents); +} + +WebContentsAdapter::~WebContentsAdapter() +{ +} + +void WebContentsAdapter::initialize(WebContentsAdapterClient *adapterClient) +{ + Q_D(WebContentsAdapter); d->adapterClient = adapterClient; - content::BrowserContext* browserContext = ContentBrowserClientQt::Get()->browser_context(); - content::WebContents::CreateParams create_params(browserContext, NULL); - create_params.routing_id = MSG_ROUTING_NONE; - create_params.initial_size = gfx::Size(kTestWindowWidth, kTestWindowHeight); - d->webContents.reset(content::WebContents::Create(create_params)); + // Create our own if a WebContents wasn't provided at construction. + if (!d->webContents) { + content::BrowserContext* browserContext = ContentBrowserClientQt::Get()->browser_context(); + content::WebContents::CreateParams create_params(browserContext, NULL); + create_params.routing_id = MSG_ROUTING_NONE; + create_params.initial_size = gfx::Size(kTestWindowWidth, kTestWindowHeight); + create_params.context = reinterpret_cast<gfx::NativeView>(adapterClient); + d->webContents.reset(content::WebContents::Create(create_params)); + } content::RendererPreferences* rendererPrefs = d->webContents->GetMutableRendererPrefs(); rendererPrefs->use_custom_colors = true; @@ -97,11 +111,7 @@ WebContentsAdapter::WebContentsAdapter(WebContentsAdapterClient *adapterClient) // Let the WebContent's view know about the WebContentsAdapterClient. WebContentsViewQt* contentsView = static_cast<WebContentsViewQt*>(d->webContents->GetView()); - contentsView->SetClient(adapterClient); -} - -WebContentsAdapter::~WebContentsAdapter() -{ + contentsView->initialize(adapterClient); } bool WebContentsAdapter::canGoBack() const diff --git a/lib/web_contents_adapter.h b/lib/web_contents_adapter.h index 15cc79f40..8b4dae1f2 100644 --- a/lib/web_contents_adapter.h +++ b/lib/web_contents_adapter.h @@ -57,8 +57,10 @@ class WebContentsAdapterPrivate; class QWEBENGINE_EXPORT WebContentsAdapter : public QSharedData { public: - WebContentsAdapter(WebContentsAdapterClient* adapterClient); + // Takes ownership of the WebContents. + WebContentsAdapter(content::WebContents *webContents = 0); ~WebContentsAdapter(); + void initialize(WebContentsAdapterClient *adapterClient); bool canGoBack() const; bool canGoForward() const; diff --git a/lib/web_contents_adapter_client.h b/lib/web_contents_adapter_client.h index fd4599f7f..e17929025 100644 --- a/lib/web_contents_adapter_client.h +++ b/lib/web_contents_adapter_client.h @@ -50,10 +50,26 @@ class RenderWidgetHostViewQt; class RenderWidgetHostViewQtDelegate; +class WebContentsAdapter; class WebContentsDelegateQt; class QWEBENGINE_EXPORT WebContentsAdapterClient { public: + // This must match window_open_disposition_list.h. + enum WindowOpenDisposition { + UnknownDisposition = 0, + SuppressOpenDisposition = 1, + CurrentTabDisposition = 2, + SingletonTabDisposition = 3, + NewForegroundTabDisposition = 4, + NewBackgroundTabDisposition = 5, + NewPopupDisposition = 6, + NewWindowDisposition = 7, + SaveToDiskDisposition = 8, + OffTheRecordDisposition = 9, + IgnoreActionDisposition = 10, + }; + virtual ~WebContentsAdapterClient() { } virtual RenderWidgetHostViewQtDelegate* CreateRenderWidgetHostViewQtDelegate() = 0; @@ -63,6 +79,7 @@ public: virtual QRectF viewportRect() const = 0; virtual void loadFinished(bool success) = 0; virtual void focusContainer() = 0; + virtual void adoptNewWindow(WebContentsAdapter *newWebContents, WindowOpenDisposition disposition) = 0; }; #endif // WEB_CONTENTS_ADAPTER_CLIENT_H diff --git a/lib/web_contents_delegate_qt.cpp b/lib/web_contents_delegate_qt.cpp index a4148e677..78de00620 100644 --- a/lib/web_contents_delegate_qt.cpp +++ b/lib/web_contents_delegate_qt.cpp @@ -63,6 +63,24 @@ void WebContentsDelegateQt::NavigationStateChanged(const content::WebContents* s m_viewClient->urlChanged(toQt(m_webContents->GetVisibleURL())); } +void WebContentsDelegateQt::AddNewContents(content::WebContents* source, content::WebContents* new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture, bool* was_blocked) +{ + WebContentsAdapter *newAdapter = new WebContentsAdapter(new_contents); + // Do the first ref-count manually to be able to know if the application is handling adoptNewWindow through the public API. + newAdapter->ref.ref(); + + m_viewClient->adoptNewWindow(newAdapter, static_cast<WebContentsAdapterClient::WindowOpenDisposition>(disposition)); + + if (!newAdapter->ref.deref()) { + // adoptNewWindow didn't increase the ref-count, new_contents needs to be discarded. + delete newAdapter; + newAdapter = 0; + } + + if (was_blocked) + *was_blocked = !newAdapter; +} + void WebContentsDelegateQt::LoadingStateChanged(content::WebContents* source) { m_viewClient->loadingStateChanged(); diff --git a/lib/web_contents_delegate_qt.h b/lib/web_contents_delegate_qt.h index 8f631855e..6568631b4 100644 --- a/lib/web_contents_delegate_qt.h +++ b/lib/web_contents_delegate_qt.h @@ -60,6 +60,7 @@ public: WebContentsDelegateQt(content::WebContents*, WebContentsAdapterClient *adapterClient); virtual void NavigationStateChanged(const content::WebContents* source, unsigned changed_flags); + virtual void AddNewContents(content::WebContents* source, content::WebContents* new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture, bool* was_blocked); virtual void LoadingStateChanged(content::WebContents* source); virtual void DidFailLoad(int64 frame_id, const GURL &validated_url, bool is_main_frame, int error_code, const string16 &error_description, content::RenderViewHost *render_view_host); virtual void DidFinishLoad(int64 frame_id, const GURL &validated_url, bool is_main_frame, content::RenderViewHost *render_view_host); diff --git a/lib/web_contents_view_qt.cpp b/lib/web_contents_view_qt.cpp index db991d84b..b74b7325a 100644 --- a/lib/web_contents_view_qt.cpp +++ b/lib/web_contents_view_qt.cpp @@ -47,24 +47,49 @@ #include "content/browser/renderer_host/render_view_host_impl.h" +void WebContentsViewQt::initialize(WebContentsAdapterClient* client) +{ + m_client = client; + + // Check if a RWHV was created before the initialization. + if (m_webContents->GetRenderWidgetHostView()) + static_cast<RenderWidgetHostViewQt *>(m_webContents->GetRenderWidgetHostView())->setAdapterClient(client); +} + content::RenderWidgetHostView* WebContentsViewQt::CreateViewForWidget(content::RenderWidgetHost* render_widget_host) { RenderWidgetHostViewQt *view = new RenderWidgetHostViewQt(render_widget_host); - RenderWidgetHostViewQtDelegate* viewDelegate = m_client->CreateRenderWidgetHostViewQtDelegate(); - view->SetDelegate(viewDelegate); - // The delegate has been bound to its view, now initialize it. - // gfx::NativeView logically maps to our client here but the reinterpret_cast is still ugly. - // The alternative is be to have a duplicated method with the proper signature. - view->InitAsChild(reinterpret_cast<gfx::NativeView>(m_client)); + + Q_ASSERT(m_factoryClient); + RenderWidgetHostViewQtDelegate* viewDelegate = m_factoryClient->CreateRenderWidgetHostViewQtDelegate(); + view->setDelegate(viewDelegate); + if (m_client) + view->setAdapterClient(m_client); + + // Tell the RWHV delegate to attach itself to the native view container. + view->InitAsChild(0); return view; } +void WebContentsViewQt::CreateView(const gfx::Size& initial_size, gfx::NativeView context) +{ + // This is passed through content::WebContents::CreateParams::context either as the native view's client + // directly or, in the case of a page-created new window, the client of the creating window's native view. + m_factoryClient = reinterpret_cast<WebContentsAdapterClient *>(context); +} + void WebContentsViewQt::SetPageTitle(const string16& title) { m_client->titleChanged(toQt(title)); } +gfx::NativeView WebContentsViewQt::GetNativeView() const +{ + // Hack to provide the client to WebContentsImpl::CreateNewWindow. + return reinterpret_cast<gfx::NativeView>(m_client); +} + void WebContentsViewQt::GetContainerBounds(gfx::Rect* out) const { const QRectF r(m_client->viewportRect()); diff --git a/lib/web_contents_view_qt.h b/lib/web_contents_view_qt.h index 0d686359b..b76c72545 100644 --- a/lib/web_contents_view_qt.h +++ b/lib/web_contents_view_qt.h @@ -58,15 +58,17 @@ class WebContentsViewQt , public content::RenderViewHostDelegateView { public: - WebContentsViewQt(content::WebContents* web_contents) - : m_client(0) + WebContentsViewQt(content::WebContents* webContents) + : m_webContents(webContents) + , m_client(0) + , m_factoryClient(0) { } - void SetClient(WebContentsAdapterClient* client) { m_client = client; } + void initialize(WebContentsAdapterClient* client); virtual content::RenderWidgetHostView *CreateViewForWidget(content::RenderWidgetHost* render_widget_host); - virtual void CreateView(const gfx::Size& initial_size, gfx::NativeView context) { QT_NOT_YET_IMPLEMENTED } + virtual void CreateView(const gfx::Size& initial_size, gfx::NativeView context); virtual content::RenderWidgetHostView* CreateViewForPopupWidget(content::RenderWidgetHost* render_widget_host) { return 0; } @@ -78,7 +80,7 @@ public: virtual void SetOverscrollControllerEnabled(bool enabled) { QT_NOT_YET_IMPLEMENTED } - virtual gfx::NativeView GetNativeView() const { QT_NOT_USED return 0; } + virtual gfx::NativeView GetNativeView() const; virtual gfx::NativeView GetContentNativeView() const { QT_NOT_USED return 0; } @@ -113,7 +115,9 @@ public: #endif // defined(OS_MACOSX) private: - WebContentsAdapterClient* m_client; + content::WebContents *m_webContents; + WebContentsAdapterClient *m_client; + WebContentsAdapterClient *m_factoryClient; }; #endif // WEB_CONTENTS_VIEW_QT_H diff --git a/lib/widgets/Api/qwebenginepage.cpp b/lib/widgets/Api/qwebenginepage.cpp index 0bc6d85e1..f3f046675 100644 --- a/lib/widgets/Api/qwebenginepage.cpp +++ b/lib/widgets/Api/qwebenginepage.cpp @@ -36,11 +36,12 @@ QWebEnginePagePrivate::QWebEnginePagePrivate() : QObjectPrivate(QObjectPrivateVersion) - , adapter(new WebContentsAdapter(this)) + , adapter(new WebContentsAdapter) , history(new QWebEngineHistory(new QWebEngineHistoryPrivate(adapter.data()))) , view(0) , m_isLoading(false) { + adapter->initialize(this); memset(actions, 0, sizeof(actions)); } @@ -96,6 +97,17 @@ void QWebEnginePagePrivate::focusContainer() view->setFocus(); } +void QWebEnginePagePrivate::adoptNewWindow(WebContentsAdapter *newWebContents, WindowOpenDisposition disposition) +{ + Q_Q(QWebEnginePage); + QWebEnginePage *newPage = q->createWindow(disposition == WebContentsAdapterClient::NewPopupDisposition ? QWebEnginePage::WebModalDialog : QWebEnginePage::WebBrowserWindow); + // Overwrite the new page's WebContents with ours. + if (newPage) { + newPage->d_func()->adapter = newWebContents; + newWebContents->initialize(newPage->d_func()); + } +} + void QWebEnginePagePrivate::updateAction(QWebEnginePage::WebAction action) const { #ifdef QT_NO_ACTION @@ -267,4 +279,15 @@ QUrl QWebEnginePage::url() const return d->adapter->activeUrl(); } +QWebEnginePage *QWebEnginePage::createWindow(WebWindowType type) +{ + Q_D(const QWebEnginePage); + if (d->view) { + QWebEngineView *newView = d->view->createWindow(type); + if (newView) + return newView->page(); + } + return 0; +} + #include "moc_qwebenginepage.cpp" diff --git a/lib/widgets/Api/qwebenginepage.h b/lib/widgets/Api/qwebenginepage.h index 0a664edf8..808ce8435 100644 --- a/lib/widgets/Api/qwebenginepage.h +++ b/lib/widgets/Api/qwebenginepage.h @@ -535,7 +535,7 @@ Q_SIGNALS: void pageChanged(); protected: - virtual QWebEnginePage *createWindow(WebWindowType type) { Q_UNUSED(type); Q_UNREACHABLE(); return 0; }; + virtual QWebEnginePage *createWindow(WebWindowType type); virtual QObject *createPlugin(const QString &classid, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues) { Q_UNUSED(classid); Q_UNUSED(url); Q_UNUSED(paramNames); Q_UNUSED(paramValues); Q_UNREACHABLE(); return 0; } virtual bool acceptNavigationRequest(QWebEngineFrame *frame, const QNetworkRequest &request, NavigationType type) { Q_UNUSED(frame); Q_UNUSED(request); Q_UNUSED(type); Q_UNREACHABLE(); return false; } diff --git a/lib/widgets/Api/qwebenginepage_p.h b/lib/widgets/Api/qwebenginepage_p.h index f43ed9522..79c40db02 100644 --- a/lib/widgets/Api/qwebenginepage_p.h +++ b/lib/widgets/Api/qwebenginepage_p.h @@ -69,6 +69,7 @@ public: virtual QRectF viewportRect() const Q_DECL_OVERRIDE; virtual void loadFinished(bool success) Q_DECL_OVERRIDE; virtual void focusContainer() Q_DECL_OVERRIDE; + virtual void adoptNewWindow(WebContentsAdapter *newWebContents, WindowOpenDisposition disposition) Q_DECL_OVERRIDE; void updateAction(QWebEnginePage::WebAction) const; void updateNavigationActions(); diff --git a/lib/widgets/Api/qwebengineview.cpp b/lib/widgets/Api/qwebengineview.cpp index 6ae19ca75..298ddac43 100644 --- a/lib/widgets/Api/qwebengineview.cpp +++ b/lib/widgets/Api/qwebengineview.cpp @@ -166,4 +166,10 @@ void QWebEngineView::reload() page()->triggerAction(QWebEnginePage::Reload); } +QWebEngineView *QWebEngineView::createWindow(QWebEnginePage::WebWindowType type) +{ + Q_UNUSED(type) + return 0; +} + #include "moc_qwebengineview.cpp" diff --git a/lib/widgets/Api/qwebengineview.h b/lib/widgets/Api/qwebengineview.h index 8cef6a4a7..40af695bb 100644 --- a/lib/widgets/Api/qwebengineview.h +++ b/lib/widgets/Api/qwebengineview.h @@ -125,10 +125,12 @@ Q_SIGNALS: void urlChanged(const QUrl&); protected: - virtual QWebEngineView *createWindow(QWebEnginePage::WebWindowType type) { Q_UNUSED(type); return 0; } + virtual QWebEngineView *createWindow(QWebEnginePage::WebWindowType type); private: Q_DECLARE_PRIVATE(QWebEngineView); + + friend class QWebEnginePage; }; #endif // QWEBENGINEVIEW_H diff --git a/tests/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/widgets/qwebenginepage/tst_qwebenginepage.cpp index e5fa60e32..bbdc6c2e9 100644 --- a/tests/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -463,8 +463,8 @@ private Q_SLOTS: void tst_QWebEnginePage::popupFormSubmission() { -#if !defined(QWEBENGINEPAGE_CREATEWINDOW) - QSKIP("QWEBENGINEPAGE_CREATEWINDOW"); +#if !defined(QWEBENGINEPAGE_EVALUATEJAVASCRIPT) + QSKIP("QWEBENGINEPAGE_EVALUATEJAVASCRIPT"); #else TestPage page; page.settings()->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, true); |