[Qt][WK2] History is not accessible in QML.
[WebKit-https.git] / Source / WebKit2 / UIProcess / qt / QtWebPageProxy.cpp
1 /*
2  * Copyright (C) 2010, 2011 Nokia Corporation and/or its subsidiary(-ies)
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this program; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  *
19  */
20
21 #include "config.h"
22 #include "QtWebPageProxy.h"
23
24 #include <qdeclarativeengine.h>
25 #include <QtQuick/qquickcanvas.h>
26 #include "qquickwebview_p.h"
27 #include "qquickwebview_p_p.h"
28 #include "qquickwebpage_p.h"
29 #include "qwebdownloaditem_p.h"
30 #include "qwebdownloaditem_p_p.h"
31 #include "qwebnavigationhistory_p.h"
32 #include "qwebnavigationhistory_p_p.h"
33 #include "qwebpreferences_p.h"
34 #include "qwebpreferences_p_p.h"
35
36 #include "DownloadProxy.h"
37 #include "DrawingAreaProxyImpl.h"
38 #include "LayerTreeHostProxy.h"
39 #include "QtDownloadManager.h"
40 #include "QtPageClient.h"
41 #include "QtWebPageEventHandler.h"
42 #include "QtWebUndoCommand.h"
43 #include "WebBackForwardList.h"
44 #include "WebContext.h"
45 #include "WebContextMenuProxyQt.h"
46 #include "WebEditCommandProxy.h"
47 #include "WebPopupMenuProxyQt.h"
48 #include "WKStringQt.h"
49 #include "WKURLQt.h"
50 #include <QDrag>
51 #include <QMimeData>
52 #include <QUndoStack>
53 #include <WebCore/DragData.h>
54 #include <WebKit2/WKFrame.h>
55 #include <WebKit2/WKPageGroup.h>
56 #include <WebKit2/WKRetainPtr.h>
57
58 using namespace WebKit;
59 using namespace WebCore;
60
61 QtWebPageProxy::QtWebPageProxy(QQuickWebPage* qmlWebPage, QQuickWebView* qmlWebView, QtPageClient *pageClient, WKContextRef contextRef, WKPageGroupRef pageGroupRef)
62     : m_qmlWebPage(qmlWebPage)
63     , m_qmlWebView(qmlWebView)
64     , m_context(contextRef ? QtWebContext::create(toImpl(contextRef)) : QtWebContext::defaultContext())
65     , m_undoStack(adoptPtr(new QUndoStack(this)))
66     , m_navigatorQtObjectEnabled(false)
67 {
68     m_webPageProxy = m_context->createWebPage(pageClient, toImpl(pageGroupRef));
69     m_navigationHistory = adoptPtr(QWebNavigationHistoryPrivate::createHistory(this, toAPI(m_webPageProxy->backForwardList())));
70 }
71
72 void QtWebPageProxy::init(QtWebPageEventHandler* eventHandler)
73 {
74     m_eventHandler = eventHandler;
75     m_webPageProxy->initializeWebPage();
76 }
77
78 QtWebPageProxy::~QtWebPageProxy()
79 {
80     m_webPageProxy->close();
81 }
82
83 void QtWebPageProxy::showContextMenu(QSharedPointer<QMenu> menu)
84 {
85     // Remove the active menu in case this function is called twice.
86     if (activeMenu)
87         activeMenu->hide();
88
89     if (menu->isEmpty())
90         return;
91
92     QWindow* window = m_qmlWebView->canvas();
93     if (!window)
94         return;
95
96     activeMenu = menu;
97
98     activeMenu->window()->winId(); // Ensure that the menu has a window
99     Q_ASSERT(activeMenu->window()->windowHandle());
100     activeMenu->window()->windowHandle()->setTransientParent(window);
101
102     QPoint menuPositionInScene = m_qmlWebView->mapToScene(menu->pos()).toPoint();
103     menu->exec(window->mapToGlobal(menuPositionInScene));
104     // The last function to get out of exec() clear the local copy.
105     if (activeMenu == menu)
106         activeMenu.clear();
107 }
108
109 void QtWebPageProxy::hideContextMenu()
110 {
111     if (activeMenu)
112         activeMenu->hide();
113 }
114
115 void QtWebPageProxy::setViewNeedsDisplay(const WebCore::IntRect&)
116 {
117     m_qmlWebPage->update();
118 }
119
120 WebCore::IntSize QtWebPageProxy::viewSize()
121 {
122     return WebCore::IntSize(m_qmlWebPage->width(), m_qmlWebPage->height());
123 }
124
125 bool QtWebPageProxy::isViewFocused()
126 {
127     return m_qmlWebView->hasFocus();
128 }
129
130 bool QtWebPageProxy::isViewVisible()
131 {
132     return m_qmlWebView->isVisible() && m_qmlWebPage->isVisible();
133 }
134
135 void QtWebPageProxy::pageDidRequestScroll(const IntPoint& pos)
136 {
137     m_qmlWebView->d_func()->scrollPositionRequested(pos);
138 }
139
140 void QtWebPageProxy::didChangeContentsSize(const IntSize& newSize)
141 {
142     m_qmlWebView->d_func()->didChangeContentsSize(newSize);
143 }
144
145 void QtWebPageProxy::didChangeViewportProperties(const WebCore::ViewportArguments& args)
146 {
147     m_qmlWebView->d_func()->didChangeViewportProperties(args);
148 }
149
150 void QtWebPageProxy::registerEditCommand(PassRefPtr<WebEditCommandProxy> command, WebPageProxy::UndoOrRedo undoOrRedo)
151 {
152     if (undoOrRedo == WebPageProxy::Undo) {
153         const QtWebUndoCommand* webUndoCommand = static_cast<const QtWebUndoCommand*>(m_undoStack->command(m_undoStack->index()));
154         if (webUndoCommand && webUndoCommand->inUndoRedo())
155             return;
156         m_undoStack->push(new QtWebUndoCommand(command));
157     }
158 }
159
160 void QtWebPageProxy::clearAllEditCommands()
161 {
162     m_undoStack->clear();
163 }
164
165 bool QtWebPageProxy::canUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo)
166 {
167     if (undoOrRedo == WebPageProxy::Undo)
168         return m_undoStack->canUndo();
169     return m_undoStack->canRedo();
170 }
171
172 void QtWebPageProxy::executeUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo)
173 {
174     if (undoOrRedo == WebPageProxy::Undo)
175         m_undoStack->undo();
176     else
177         m_undoStack->redo();
178 }
179
180 void QtWebPageProxy::selectionChanged(bool, bool, bool, bool)
181 {
182 }
183
184 PassRefPtr<WebPopupMenuProxy> QtWebPageProxy::createPopupMenuProxy(WebPageProxy*)
185 {
186     return WebPopupMenuProxyQt::create(m_webPageProxy.get(), m_qmlWebView);
187 }
188
189 WKPageRef QtWebPageProxy::pageRef() const
190 {
191     return toAPI(m_webPageProxy.get());;
192 }
193
194 void QtWebPageProxy::didReceiveMessageFromNavigatorQtObject(const String& message)
195 {
196     QVariantMap variantMap;
197     variantMap.insert(QLatin1String("data"), QString(message));
198     variantMap.insert(QLatin1String("origin"), url());
199     emit receivedMessageFromNavigatorQtObject(variantMap);
200 }
201
202 bool QtWebPageProxy::canGoBack() const
203 {
204     return m_webPageProxy->canGoBack();
205 }
206
207 void QtWebPageProxy::goBack()
208 {
209     m_webPageProxy->goBack();
210 }
211
212 void QtWebPageProxy::goBackTo(int index)
213 {
214     m_navigationHistory->d->goBackTo(index);
215 }
216
217 bool QtWebPageProxy::canGoForward() const
218 {
219     return m_webPageProxy->canGoForward();
220 }
221
222 void QtWebPageProxy::goForward()
223 {
224     m_webPageProxy->goForward();
225 }
226
227 void QtWebPageProxy::goForwardTo(int index)
228 {
229     m_navigationHistory->d->goForwardTo(index);
230 }
231
232 bool QtWebPageProxy::loading() const
233 {
234     RefPtr<WebKit::WebFrameProxy> mainFrame = m_webPageProxy->mainFrame();
235     return mainFrame && !(WebFrameProxy::LoadStateFinished == mainFrame->loadState());
236 }
237
238 void QtWebPageProxy::stop()
239 {
240     m_webPageProxy->stopLoading();
241 }
242
243 bool QtWebPageProxy::canReload() const
244 {
245     RefPtr<WebKit::WebFrameProxy> mainFrame = m_webPageProxy->mainFrame();
246     if (mainFrame)
247         return (WebFrameProxy::LoadStateFinished == mainFrame->loadState());
248     return m_webPageProxy->backForwardList()->currentItem();
249 }
250
251 void QtWebPageProxy::reload()
252 {
253     m_webPageProxy->reload(/* reloadFromOrigin */ true);
254 }
255
256 void QtWebPageProxy::updateNavigationState()
257 {
258     emit m_qmlWebView->navigationStateChanged();
259 }
260
261 void QtWebPageProxy::didRelaunchProcess()
262 {
263     updateNavigationState();
264     qWarning("WARNING: The web process has been successfully restarted.");
265     setDrawingAreaSize(viewSize());
266 }
267
268 void QtWebPageProxy::processDidCrash()
269 {
270     updateNavigationState();
271
272     ASSERT(m_eventHandler);
273     m_eventHandler->resetGestureRecognizers();
274
275     WebCore::KURL url(WebCore::ParsedURLString, m_webPageProxy->urlAtProcessExit());
276     qWarning("WARNING: The web process experienced a crash on '%s'.", qPrintable(QUrl(url).toString(QUrl::RemoveUserInfo)));
277 }
278
279 QWebPreferences* QtWebPageProxy::preferences() const
280 {
281     if (!m_preferences)
282         m_preferences = adoptPtr(QWebPreferencesPrivate::createPreferences(const_cast<QtWebPageProxy*>(this)));
283     return m_preferences.get();
284 }
285
286 void QtWebPageProxy::setCustomUserAgent(const QString& userAgent)
287 {
288     WKRetainPtr<WKStringRef> wkUserAgent(WKStringCreateWithQString(userAgent));
289     WKPageSetCustomUserAgent(pageRef(), wkUserAgent.get());
290 }
291
292 QString QtWebPageProxy::customUserAgent() const
293 {
294     return WKStringCopyQString(WKPageCopyCustomUserAgent(pageRef()));
295 }
296
297 void QtWebPageProxy::setNavigatorQtObjectEnabled(bool enabled)
298 {
299     ASSERT(enabled != m_navigatorQtObjectEnabled);
300     // FIXME: Currently we have to keep this information in both processes and the setting is asynchronous.
301     m_navigatorQtObjectEnabled = enabled;
302     m_context->setNavigatorQtObjectEnabled(m_webPageProxy.get(), enabled);
303 }
304
305 void QtWebPageProxy::postMessageToNavigatorQtObject(const QString& message)
306 {
307     m_context->postMessageToNavigatorQtObject(m_webPageProxy.get(), message);
308 }
309
310 void QtWebPageProxy::loadHTMLString(const QString& html, const QUrl& baseUrl)
311 {
312     WKRetainPtr<WKURLRef> wkUrl(WKURLCreateWithQUrl(baseUrl));
313     WKRetainPtr<WKStringRef> wkHtmlString(WKStringCreateWithQString(html));
314
315     WKPageLoadHTMLString(pageRef(), wkHtmlString.get(), wkUrl.get());
316 }
317
318 void QtWebPageProxy::load(const QUrl& url)
319 {
320     WKRetainPtr<WKURLRef> wkurl = adoptWK(WKURLCreateWithQUrl(url));
321     WKPageLoadURL(pageRef(), wkurl.get());
322 }
323
324 QUrl QtWebPageProxy::url() const
325 {
326     WKRetainPtr<WKFrameRef> frame = WKPageGetMainFrame(pageRef());
327     if (!frame)
328         return QUrl();
329     return WKURLCopyQUrl(adoptWK(WKFrameCopyURL(frame.get())).get());
330 }
331
332 QString QtWebPageProxy::title() const
333 {
334     return WKStringCopyQString(adoptWK(WKPageCopyTitle(toAPI(m_webPageProxy.get()))).get());
335 }
336
337 void QtWebPageProxy::setDrawingAreaSize(const QSize& size)
338 {
339     if (!m_webPageProxy->drawingArea())
340         return;
341
342     m_webPageProxy->drawingArea()->setSize(IntSize(size), IntSize());
343 }
344
345 qreal QtWebPageProxy::textZoomFactor() const
346 {
347     return WKPageGetTextZoomFactor(pageRef());
348 }
349
350 void QtWebPageProxy::setTextZoomFactor(qreal zoomFactor)
351 {
352     WKPageSetTextZoomFactor(pageRef(), zoomFactor);
353 }
354
355 qreal QtWebPageProxy::pageZoomFactor() const
356 {
357     return WKPageGetPageZoomFactor(pageRef());
358 }
359
360 void QtWebPageProxy::setPageZoomFactor(qreal zoomFactor)
361 {
362     WKPageSetPageZoomFactor(pageRef(), zoomFactor);
363 }
364
365 void QtWebPageProxy::setPageAndTextZoomFactors(qreal pageZoomFactor, qreal textZoomFactor)
366 {
367     WKPageSetPageAndTextZoomFactors(pageRef(), pageZoomFactor, textZoomFactor);
368 }
369
370 QWebNavigationHistory* QtWebPageProxy::navigationHistory() const
371 {
372     return m_navigationHistory.get();
373 }
374
375 void QtWebPageProxy::handleDownloadRequest(DownloadProxy* download)
376 {
377     // This function is responsible for hooking up a DownloadProxy to our API layer
378     // by creating a QWebDownloadItem. It will then wait for the QWebDownloadItem to be
379     // ready (filled with the ResourceResponse information) so we can pass it through to
380     // our WebViews.
381     QWebDownloadItem* downloadItem = new QWebDownloadItem();
382     downloadItem->d->downloadProxy = download;
383
384     connect(downloadItem->d, SIGNAL(receivedResponse(QWebDownloadItem*)), this, SLOT(didReceiveDownloadResponse(QWebDownloadItem*)));
385     m_context->downloadManager()->addDownload(download, downloadItem);
386 }
387
388 void QtWebPageProxy::didReceiveDownloadResponse(QWebDownloadItem* downloadItem)
389 {
390     // Now that our downloadItem has everything we need we can emit downloadRequested.
391     if (!downloadItem)
392         return;
393
394     QDeclarativeEngine::setObjectOwnership(downloadItem, QDeclarativeEngine::JavaScriptOwnership);
395     emit m_qmlWebView->experimental()->downloadRequested(downloadItem);
396 }
397
398 PassOwnPtr<DrawingAreaProxy> QtWebPageProxy::createDrawingAreaProxy()
399 {
400     return DrawingAreaProxyImpl::create(m_webPageProxy.get());
401 }
402
403 void QtWebPageProxy::renderToCurrentGLContext(const TransformationMatrix& transform, float opacity)
404 {
405     DrawingAreaProxy* drawingArea = m_webPageProxy->drawingArea();
406     if (drawingArea)
407         drawingArea->paintToCurrentGLContext(transform, opacity);
408 }
409
410 void QtWebPageProxy::purgeGLResources()
411 {
412     DrawingAreaProxy* drawingArea = m_webPageProxy->drawingArea();
413     if (drawingArea && drawingArea->layerTreeHostProxy())
414         drawingArea->layerTreeHostProxy()->purgeGLResources();
415 }
416
417 void QtWebPageProxy::setVisibleContentRectAndScale(const QRectF& visibleContentRect, float scale)
418 {
419     if (!m_webPageProxy->drawingArea())
420         return;
421
422     QRect alignedVisibleContentRect = visibleContentRect.toAlignedRect();
423     m_webPageProxy->drawingArea()->setVisibleContentsRectAndScale(alignedVisibleContentRect, scale);
424
425     // FIXME: Once we support suspend and resume, this should be delayed until the page is active if the page is suspended.
426     m_webPageProxy->setFixedVisibleContentRect(alignedVisibleContentRect);
427 }
428
429 void QtWebPageProxy::setVisibleContentRectTrajectoryVector(const QPointF& trajectoryVector)
430 {
431     if (!m_webPageProxy->drawingArea())
432         return;
433
434     m_webPageProxy->drawingArea()->setVisibleContentRectTrajectoryVector(trajectoryVector);
435 }
436
437 #include "moc_QtWebPageProxy.cpp"