Source/WebKit2/ChangeLog

 12013-02-12 Jocelyn Turcotte <jocelyn.turcotte@digia.com>
 2
 3 [Qt] Properly layer QtWebContext on top of the C API
 4 https://bugs.webkit.org/show_bug.cgi?id=108475
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 The lifetime of the WebContext is difficult to manage since a circular
 9 reference is kept with the WebProcessProxy until it shuts itself down, 60
 10 seconds after the last page is closed. There was some notification
 11 in place to handle this in the upper layer, but having to go through the
 12 C API makes this quite awkward.
 13
 14 The biggest behavior change that this introduces is that the WebContext
 15 isn't automatically destroyed anymore and will be kept alive until the
 16 application is shut down.
 17 This includes the icon database, ideally we should only enable it once the
 18 QQuickWebView::icon property is read.
 19
 20 Also, instead of going through WebPageProxy and PageClient to forward
 21 injected bundle messages received by the context, maintain a static map
 22 of QQuickWebViewPrivate and fetch it using the WKPageRef.
 23
 24 * UIProcess/API/qt/qquickwebview.cpp:
 25 (QQuickWebViewPrivate::get):
 26 (QQuickWebViewPrivate::QQuickWebViewPrivate):
 27 (QQuickWebViewPrivate::~QQuickWebViewPrivate):
 28 (QQuickWebViewPrivate::initialize):
 29 (QQuickWebViewPrivate::handleDownloadRequest):
 30 (QQuickWebViewPrivate::updateIcon):
 31 (QQuickWebViewPrivate::didReceiveMessageFromNavigatorQtObject):
 32 * UIProcess/API/qt/qquickwebview_p_p.h:
 33 (QQuickWebViewPrivate):
 34 * UIProcess/API/qt/qwebiconimageprovider.cpp:
 35 (QWebIconImageProvider::requestImage):
 36 * UIProcess/API/qt/raw/qrawwebview.cpp:
 37 * UIProcess/API/qt/raw/qrawwebview_p_p.h:
 38 * UIProcess/PageClient.h:
 39 (PageClient):
 40 * UIProcess/WebPageProxy.h:
 41 (WebPageProxy):
 42 * UIProcess/qt/QtPageClient.cpp:
 43 * UIProcess/qt/QtPageClient.h:
 44 (QtPageClient):
 45 * UIProcess/qt/QtWebContext.cpp:
 46 (WebKit):
 47 (WebKit::didReceiveMessageFromInjectedBundle):
 48 (WebKit::initializeContextInjectedBundleClient):
 49 (WebKit::QtWebContext::QtWebContext):
 50 (WebKit::QtWebContext::~QtWebContext):
 51 (WebKit::QtWebContext::create):
 52 (WebKit::QtWebContext::defaultContext):
 53 * UIProcess/qt/QtWebContext.h:
 54 (WebKit):
 55 (QtWebContext):
 56 (WebKit::QtWebContext::context):
 57 (WebKit::QtWebContext::downloadManager):
 58 (WebKit::QtWebContext::iconDatabase):
 59 * UIProcess/qt/WebContextQt.cpp:
 60 (WebKit::WebContext::platformInvalidateContext):
 61 * UIProcess/qt/WebPageProxyQt.cpp:
 62
1632013-02-11 Jocelyn Turcotte <jocelyn.turcotte@digia.com>
264
365 [Qt][WK2] Favor QUrl to WTF::String in the Qt API layer

Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp

3434#include "QtWebPageEventHandler.h"
3535#include "QtWebPagePolicyClient.h"
3636#include "WebBackForwardList.h"
 37#include "WebContext.h"
3738#include "WebFindOptions.h"
3839#if ENABLE(INSPECTOR_SERVER)
3940#include "WebInspectorProxy.h"

4445#endif
4546#include "WebPageGroup.h"
4647#include "WebPreferences.h"
 48#include "qglobal.h"
4749#include "qquicknetworkreply_p.h"
4850#include "qquicknetworkrequest_p.h"
4951#include "qquickwebpage_p_p.h"

6062#include <JavaScriptCore/JSBase.h>
6163#include <JavaScriptCore/JSRetainPtr.h>
6264#include <QDateTime>
 65#include <QMap>
6366#include <QtCore/QFile>
6467#include <QtQml/QJSValue>
6568#include <QtQuick/QQuickView>

@@static const int kAxisLockSampleCount = 5;
8588static const qreal kAxisLockVelocityThreshold = 300;
8689static const qreal kAxisLockVelocityDirectionThreshold = 50;
8790
 91typedef QMap<WKPageRef, QQuickWebViewPrivate*> PageToViewMap;
 92Q_GLOBAL_STATIC(PageToViewMap, pageToView)
 93
8894static inline QQuickWebViewPrivate* toQQuickWebViewPrivate(const void* clientInfo)
8995{
9096 ASSERT(clientInfo);

@@static QQuickWebViewPrivate* createPrivateObject(QQuickWebView* publicObject)
197203 return new QQuickWebViewLegacyPrivate(publicObject);
198204}
199205
 206QQuickWebViewPrivate* QQuickWebViewPrivate::get(WKPageRef page)
 207{
 208 return pageToView()->value(page);
 209}
 210
200211QQuickWebViewPrivate::FlickableAxisLocker::FlickableAxisLocker()
201212 : m_allowedDirection(QQuickFlickable::AutoFlickDirection)
202213 , m_time(0), m_sampleCount(0)

@@QPointF QQuickWebViewPrivate::FlickableAxisLocker::adjust(const QPointF& positio
272283QQuickWebViewPrivate::QQuickWebViewPrivate(QQuickWebView* viewport)
273284 : q_ptr(viewport)
274285 , experimental(new QQuickWebViewExperimental(viewport, this))
 286 , context(0)
275287 , alertDialog(0)
276288 , confirmDialog(0)
277289 , promptDialog(0)

@@QQuickWebViewPrivate::QQuickWebViewPrivate(QQuickWebView* viewport)
299311QQuickWebViewPrivate::~QQuickWebViewPrivate()
300312{
301313 webPageProxy->close();
 314 pageToView()->remove(webPage.get());
302315}
303316
304317// Note: we delay this initialization to make sure that QQuickWebView has its d-ptr in-place.

@@void QQuickWebViewPrivate::initialize(WKContextRef contextRef, WKPageGroupRef pa
308321 if (!pageGroup)
309322 pageGroup = adoptWK(WKPageGroupCreateWithIdentifier(0));
310323
311  context = contextRef ? QtWebContext::create(toImpl(contextRef)) : QtWebContext::defaultContext();
312  webPageProxy = context->createWebPage(&pageClient, toImpl(pageGroup.get()));
 324 context = contextRef ? QtWebContext::create(contextRef) : QtWebContext::defaultContext();
 325 webPageProxy = toImpl(context->context())->createWebPage(&pageClient, toImpl(pageGroup.get()));
313326 webPage = toAPI(webPageProxy.get());
 327 pageToView()->insert(webPage.get(), this);
 328
314329 webPageProxy->setUseFixedLayout(s_flickableViewportEnabled);
315330#if ENABLE(FULLSCREEN_API)
316331 webPageProxy->fullScreenManager()->setWebView(q_ptr);

@@void QQuickWebViewPrivate::handleDownloadRequest(DownloadProxy* download)
607622 downloadItem->d->downloadProxy = download;
608623
609624 q->connect(downloadItem->d, SIGNAL(receivedResponse(QWebDownloadItem*)), q, SLOT(_q_onReceivedResponseFromDownload(QWebDownloadItem*)));
610  QtWebContext::downloadManager()->addDownload(download, downloadItem);
 625 QtWebContext::defaultContext()->downloadManager()->addDownload(download, downloadItem);
611626}
612627
613628void QQuickWebViewPrivate::_q_onVisibleChanged()

@@void QQuickWebViewPrivate::updateIcon()
642657 if (!provider)
643658 return;
644659
645  QUrl iconUrl = provider->iconURLForPageURLInContext(m_currentUrl, context.get());
 660 QUrl iconUrl = provider->iconURLForPageURLInContext(m_currentUrl, context);
646661
647662 if (iconUrl == m_iconUrl)
648663 return;

@@WebCore::IntSize QQuickWebViewPrivate::viewSize() const
896911
897912 \sa postMessage
898913*/
899 void QQuickWebViewPrivate::didReceiveMessageFromNavigatorQtObject(const String& message)
 914void QQuickWebViewPrivate::didReceiveMessageFromNavigatorQtObject(WKStringRef message)
900915{
901916 QVariantMap variantMap;
902  variantMap.insert(QLatin1String("data"), QString(message));
 917 variantMap.insert(QLatin1String("data"), WKStringCopyQString(message));
903918 variantMap.insert(QLatin1String("origin"), q_ptr->url());
904919 emit q_ptr->experimental()->messageReceived(variantMap);
905920}

Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h

@@class QQuickWebViewPrivate {
6565
6666public:
6767 static QQuickWebViewPrivate* get(QQuickWebView* q) { return q->d_ptr.data(); }
 68 static QQuickWebViewPrivate* get(WKPageRef);
6869
6970 virtual ~QQuickWebViewPrivate();
7071

@@public:
123124
124125 // PageClient.
125126 WebCore::IntSize viewSize() const;
126  void didReceiveMessageFromNavigatorQtObject(const String& message);
127127 virtual void pageDidRequestScroll(const QPoint& pos) { }
128128 void processDidCrash();
129129 void didRelaunchProcess();
130130 PassOwnPtr<WebKit::DrawingAreaProxy> createDrawingAreaProxy();
131131 void handleDownloadRequest(WebKit::DownloadProxy*);
132132
 133 void didReceiveMessageFromNavigatorQtObject(WKStringRef message);
 134
133135protected:
134136 class FlickableAxisLocker {
135137 QQuickFlickable::FlickableDirection m_allowedDirection;

@@protected:
164166 static void didChangeBackForwardList(WKPageRef, WKBackForwardListItemRef, WKArrayRef, const void *clientInfo);
165167
166168 QQuickWebViewPrivate(QQuickWebView* viewport);
167  RefPtr<WebKit::QtWebContext> context;
168169 RefPtr<WebKit::WebPageProxy> webPageProxy;
169170 WKRetainPtr<WKPageRef> webPage;
170171 WKRetainPtr<WKPageGroupRef> pageGroup;

@@protected:
180181 QScopedPointer<QQuickWebPage> pageView;
181182 QQuickWebView* q_ptr;
182183 QQuickWebViewExperimental* experimental;
 184 WebKit::QtWebContext* context;
183185
184186 FlickableAxisLocker axisLocker;
185187

Source/WebKit2/UIProcess/API/qt/qwebiconimageprovider.cpp

@@QImage QWebIconImageProvider::requestImage(const QString& id, QSize* size, const
6767{
6868 QUrl pageURL = QUrl::fromEncoded(QByteArray::fromBase64(id.midRef(id.indexOf('#') + 1).toLatin1()));
6969
70  QtWebIconDatabaseClient* iconDatabase = QtWebContext::iconDatabase();
 70 QtWebIconDatabaseClient* iconDatabase = QtWebContext::defaultContext()->iconDatabase();
7171 if (!iconDatabase)
7272 return QImage();
7373

Source/WebKit2/UIProcess/API/qt/raw/qrawwebview.cpp

3737#include <WebCore/CoordinatedGraphicsScene.h>
3838#include <WebKit2/qrawwebview_p.h>
3939
40 void QRawWebViewPrivate::didReceiveMessageFromNavigatorQtObject(const String& message)
41 {
42  notImplemented();
43 }
44 
4540void QRawWebViewPrivate::didChangeViewportProperties(const WebCore::ViewportAttributes& attr)
4641{
4742 notImplemented();

Source/WebKit2/UIProcess/API/qt/raw/qrawwebview_p_p.h

@@public:
4646 virtual void countStringMatchesInCustomRepresentation(const String&, WebKit::FindOptions, unsigned maxMatchCount) { }
4747 virtual void clearAllEditCommands() { }
4848
49  virtual void didReceiveMessageFromNavigatorQtObject(const String& message);
5049 virtual void didChangeViewportProperties(const WebCore::ViewportAttributes& attr);
5150 virtual void handleDownloadRequest(WebKit::DownloadProxy* download);
5251

Source/WebKit2/UIProcess/PageClient.h

@@public:
121121#endif
122122#if PLATFORM(QT)
123123 virtual void didFindZoomableArea(const WebCore::IntPoint&, const WebCore::IntRect&) = 0;
124  virtual void didReceiveMessageFromNavigatorQtObject(const String&) = 0;
125124 virtual void handleAuthenticationRequiredRequest(const String& hostname, const String& realm, const String& prefilledUsername, String& username, String& password) = 0;
126125 virtual void handleCertificateVerificationRequest(const String& hostname, bool& ignoreErrors) = 0;
127126 virtual void handleProxyAuthenticationRequiredRequest(const String& hostname, uint16_t port, const String& prefilledUsername, String& username, String& password) = 0;

Source/WebKit2/UIProcess/WebPageProxy.h

@@public:
642642
643643#if PLATFORM(QT)
644644 void findZoomableAreaForPoint(const WebCore::IntPoint&, const WebCore::IntSize&);
645  void didReceiveMessageFromNavigatorQtObject(const String&);
646645#endif
647646
648647#if PLATFORM(QT) || PLATFORM(EFL) || PLATFORM(GTK)

Source/WebKit2/UIProcess/qt/QtPageClient.cpp

@@void QtPageClient::didFindZoomableArea(const IntPoint& target, const IntRect& ar
245245 m_eventHandler->didFindZoomableArea(target, area);
246246}
247247
248 void QtPageClient::didReceiveMessageFromNavigatorQtObject(const String& message)
249 {
250  QQuickWebViewPrivate::get(m_webView)->didReceiveMessageFromNavigatorQtObject(message);
251 }
252 
253248void QtPageClient::updateTextInputState()
254249{
255250 ASSERT(m_eventHandler);

Source/WebKit2/UIProcess/qt/QtPageClient.h

@@public:
4747 virtual WebCore::IntSize viewSize();
4848 virtual bool isViewFocused();
4949 virtual bool isViewVisible();
50  virtual void didReceiveMessageFromNavigatorQtObject(const String&);
5150 virtual void pageDidRequestScroll(const WebCore::IntPoint&);
5251 virtual void didChangeContentsSize(const WebCore::IntSize&);
5352 virtual void didChangeViewportProperties(const WebCore::ViewportAttributes&);

Source/WebKit2/UIProcess/qt/QtWebContext.cpp

2323
2424#include "QtDownloadManager.h"
2525#include "QtWebIconDatabaseClient.h"
26 #include "WKAPICast.h"
27 #include "WebContext.h"
2826#include "WebInspectorServer.h"
29 #include "WebPageProxy.h"
 27#include "qquickwebview_p_p.h"
 28#include <WKAPICast.h>
3029#include <WKArray.h>
3130#include <WKPage.h>
3231#include <WKString.h>

3433
3534namespace WebKit {
3635
37 static WebContext* s_defaultWebContext = 0;
 36// Prevent the destruction of the WKContext for two reasons:
 37// - An internal reference is kept to the WebContext waiting until the web process shut down, which
 38// does so 60 seconds after the last page closed. We want to reuse that web process if possible and
 39// avoid creating a second parallel WKContext + web process.
 40// - The IconDatabase wasn't designed to have more than one instance, or to be quickly opened/closed.
3841static QtWebContext* s_defaultQtWebContext = 0;
39 static OwnPtr<QtDownloadManager> s_downloadManager;
40 static OwnPtr<QtWebIconDatabaseClient> s_iconDatabase;
4142
4243static void initInspectorServer()
4344{

@@static void didReceiveMessageFromInjectedBundle(WKContextRef, WKStringRef messag
9798 WKPageRef page = static_cast<WKPageRef>(WKArrayGetItemAtIndex(body, 0));
9899 WKStringRef str = static_cast<WKStringRef>(WKArrayGetItemAtIndex(body, 1));
99100
100  toImpl(page)->didReceiveMessageFromNavigatorQtObject(toImpl(str)->string());
 101 QQuickWebViewPrivate::get(page)->didReceiveMessageFromNavigatorQtObject(str);
101102}
102103
103 static void initializeContextInjectedBundleClient(WebContext* context)
 104static void initializeContextInjectedBundleClient(WKContextRef context)
104105{
105106 WKContextInjectedBundleClient injectedBundleClient;
106107 memset(&injectedBundleClient, 0, sizeof(WKContextInjectedBundleClient));
107108 injectedBundleClient.version = kWKContextInjectedBundleClientCurrentVersion;
108109 injectedBundleClient.didReceiveMessageFromInjectedBundle = didReceiveMessageFromInjectedBundle;
109  WKContextSetInjectedBundleClient(toAPI(context), &injectedBundleClient);
 110 WKContextSetInjectedBundleClient(context, &injectedBundleClient);
110111}
111112
112 QtWebContext::QtWebContext(WebContext* context)
 113QtWebContext::QtWebContext(WKContextRef context)
113114 : m_context(context)
 115 , m_downloadManager(new QtDownloadManager(toImpl(context)))
 116 , m_iconDatabase(new QtWebIconDatabaseClient(toImpl(context)))
114117{
115118}
116119
117120QtWebContext::~QtWebContext()
118121{
119  ASSERT(!s_defaultQtWebContext || s_defaultQtWebContext == this);
120  s_defaultQtWebContext = 0;
121122}
122123
123124// Used directly only by WebKitTestRunner.
124 PassRefPtr<QtWebContext> QtWebContext::create(WebContext* context)
 125QtWebContext* QtWebContext::create(WKContextRef context)
125126{
126127 globalInitialization();
127  // The lifetime of WebContext is a bit special, it is bound to the reference held
128  // by QtWebContext at first and then enters a circular dependency with WebProcessProxy
129  // once the first page is created until the web process exits. Because of this we can't
130  // assume that destroying the last QtWebContext will destroy the WebContext and we
131  // have to make sure that WebContext's clients follow its lifetime and aren't attached
132  // to QtWebContext. QtWebContext itself is only attached to QQuickWebView.
133  // Since we only support one WebContext at a time, initialize those clients globally
134  // here. They have to be available to views spawned by WebKitTestRunner as well.
135  if (!s_downloadManager)
136  s_downloadManager = adoptPtr(new QtDownloadManager(context));
137  if (!s_iconDatabase)
138  s_iconDatabase = adoptPtr(new QtWebIconDatabaseClient(context));
139  return adoptRef(new QtWebContext(context));
 128 return new QtWebContext(context);
140129}
141130
142 PassRefPtr<QtWebContext> QtWebContext::defaultContext()
 131QtWebContext* QtWebContext::defaultContext()
143132{
144  // Keep local references until we can return a ref to QtWebContext holding the WebContext.
145  RefPtr<WebContext> webContext(s_defaultWebContext);
146  RefPtr<QtWebContext> qtWebContext(s_defaultQtWebContext);
147 
148  if (!webContext) {
149  webContext = WebContext::create(String());
150  s_defaultWebContext = webContext.get();
 133 if (!s_defaultQtWebContext) {
 134 WKRetainPtr<WKContextRef> wkContext = adoptWK(WKContextCreate());
151135 // Make sure for WebKitTestRunner that the injected bundle client isn't initialized
152  // and that the page cache isn't enabled (defaultContext isn't used there).
153  initializeContextInjectedBundleClient(webContext.get());
 136 // and that the page cache isn't enabled (defaultContext() isn't used there).
 137 initializeContextInjectedBundleClient(wkContext.get());
154138 // A good all-around default.
155  webContext->setCacheModel(CacheModelDocumentBrowser);
156  }
 139 WKContextSetCacheModel(wkContext.get(), kWKCacheModelDocumentBrowser);
157140
158  if (!qtWebContext) {
159  qtWebContext = QtWebContext::create(webContext.get());
160  s_defaultQtWebContext = qtWebContext.get();
 141 s_defaultQtWebContext = QtWebContext::create(wkContext.get());
161142 }
162143
163  return qtWebContext.release();
164 }
165 
166 PassRefPtr<WebPageProxy> QtWebContext::createWebPage(PageClient* client, WebPageGroup* pageGroup)
167 {
168  return m_context->createWebPage(client, pageGroup);
169 }
170 
171 QtDownloadManager* QtWebContext::downloadManager()
172 {
173  ASSERT(s_downloadManager);
174  return s_downloadManager.get();
175 }
176 
177 QtWebIconDatabaseClient* QtWebContext::iconDatabase()
178 {
179  ASSERT(s_iconDatabase);
180  return s_iconDatabase.get();
181 }
182 
183 void QtWebContext::invalidateContext(WebContext* context)
184 {
185  UNUSED_PARAM(context);
186  ASSERT(!s_defaultQtWebContext);
187  ASSERT(!s_defaultWebContext || s_defaultWebContext == context);
188  s_downloadManager.clear();
189  s_iconDatabase.clear();
190  s_defaultWebContext = 0;
 144 return s_defaultQtWebContext;
191145}
192146
193147} // namespace WebKit

Source/WebKit2/UIProcess/qt/QtWebContext.h

2121#ifndef QtWebContext_h
2222#define QtWebContext_h
2323
 24#include <QScopedPointer>
2425#include <QtGlobal>
2526#include <WKContext.h>
26 #include <wtf/OwnPtr.h>
27 #include <wtf/PassRefPtr.h>
28 #include <wtf/RefCounted.h>
29 #include <wtf/RefPtr.h>
 27#include <WKRetainPtr.h>
3028
3129namespace WebKit {
3230
33 class PageClient;
3431class QtDownloadManager;
3532class QtWebIconDatabaseClient;
36 class WebContext;
37 class WebPageGroup;
38 class WebPageProxy;
3933
40 class QtWebContext : public RefCounted<QtWebContext> {
 34class QtWebContext {
4135public:
4236 ~QtWebContext();
4337
44  static PassRefPtr<QtWebContext> create(WebContext*);
45  static PassRefPtr<QtWebContext> defaultContext();
 38 static QtWebContext* create(WKContextRef);
 39 static QtWebContext* defaultContext();
4640
47  PassRefPtr<WebPageProxy> createWebPage(PageClient*, WebPageGroup*);
 41 WKContextRef context() { return m_context.get(); }
4842
49  WebContext* context() { return m_context.get(); }
50 
51  static QtDownloadManager* downloadManager();
52  static QtWebIconDatabaseClient* iconDatabase();
53  static void invalidateContext(WebContext*);
 43 QtDownloadManager* downloadManager() { return m_downloadManager.data(); }
 44 QtWebIconDatabaseClient* iconDatabase() { return m_iconDatabase.data(); }
5445
5546private:
56  explicit QtWebContext(WebContext*);
 47 explicit QtWebContext(WKContextRef);
5748
58  RefPtr<WebContext> m_context;
 49 WKRetainPtr<WKContextRef> m_context;
 50 QScopedPointer<QtDownloadManager> m_downloadManager;
 51 QScopedPointer<QtWebIconDatabaseClient> m_iconDatabase;
5952};
6053
6154} // namespace WebKit

Source/WebKit2/UIProcess/qt/WebContextQt.cpp

@@void WebContext::platformInitializeWebProcess(WebProcessCreationParameters& para
8181
8282void WebContext::platformInvalidateContext()
8383{
84 #if HAVE(QTQUICK)
85  QtWebContext::invalidateContext(this);
86 #endif
8784}
8885
8986String WebContext::platformDefaultDatabaseDirectory() const

Source/WebKit2/UIProcess/qt/WebPageProxyQt.cpp

@@void WebPageProxy::findZoomableAreaForPoint(const IntPoint& point, const IntSize
9999 m_process->send(Messages::WebPage::FindZoomableAreaForPoint(point, area), m_pageID);
100100}
101101
102 void WebPageProxy::didReceiveMessageFromNavigatorQtObject(const String& contents)
103 {
104  m_pageClient->didReceiveMessageFromNavigatorQtObject(contents);
105 }
106 
107102void WebPageProxy::authenticationRequiredRequest(const String& hostname, const String& realm, const String& prefilledUsername, String& username, String& password)
108103{
109104 m_pageClient->handleAuthenticationRequiredRequest(hostname, realm, prefilledUsername, username, password);