1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the QtWebView module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL3$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or later as published by the Free
28** Software Foundation and appearing in the file LICENSE.GPL included in
29** the packaging of this file. Please review the following information to
30** ensure the GNU General Public License version 2.0 requirements will be
31** met: http://www.gnu.org/licenses/gpl-2.0.html.
32**
33** $QT_END_LICENSE$
34**
35****************************************************************************/
36
37#include "qquickwebview_p.h"
38#include "qquickwebviewloadrequest_p.h"
39#include <QtWebView/private/qwebviewloadrequest_p.h>
40#include <QtQml/qqmlengine.h>
41#include <QtCore/qmutex.h>
42
43namespace {
44
45class CallbackStorage
46{
47public:
48 int insertCallback(const QJSValue &callback)
49 {
50 QMutexLocker locker(&m_mtx);
51 const int nextId = qMax(a: ++m_counter, b: 0);
52 if (nextId == 0)
53 m_counter = 1;
54
55 m_callbacks.insert(akey: nextId, avalue: callback);
56 return nextId;
57 }
58
59 QJSValue takeCallback(int callbackId)
60 {
61 QMutexLocker lock(&m_mtx);
62 return m_callbacks.take(akey: callbackId);
63 }
64
65private:
66 QMutex m_mtx;
67 int m_counter;
68 QHash<int, QJSValue> m_callbacks;
69};
70
71} // namespace
72
73Q_GLOBAL_STATIC(CallbackStorage, callbacks)
74
75/*!
76 \qmltype WebView
77 \inqmlmodule QtWebView
78 \ingroup qtwebview
79 \brief A component for displaying web content.
80
81 WebView is a component for displaying web content which is implemented using native
82 APIs on the platforms where this is available, thus it does not necessarily require
83 including a full web browser stack as part of the application.
84
85 To make the Qt WebView module function correctly across all platforms, it is necessary
86 to call \l {qtwebview-initialize}{QtWebView::initialize}() right after creating the
87 QGuiApplication instance.
88
89 \note Due to platform limitations overlapping the WebView and other QML components
90 is not supported.
91*/
92
93QQuickWebView::QQuickWebView(QQuickItem *parent)
94 : QQuickViewController(parent)
95 , m_webView(new QWebView(this))
96{
97 setView(m_webView);
98 connect(sender: m_webView, signal: &QWebView::titleChanged, receiver: this, slot: &QQuickWebView::titleChanged);
99 connect(sender: m_webView, signal: &QWebView::urlChanged, receiver: this, slot: &QQuickWebView::urlChanged);
100 connect(sender: m_webView, signal: &QWebView::loadProgressChanged, receiver: this, slot: &QQuickWebView::loadProgressChanged);
101 connect(sender: m_webView, signal: &QWebView::loadingChanged, receiver: this, slot: &QQuickWebView::onLoadingChanged);
102 connect(sender: m_webView, signal: &QWebView::requestFocus, receiver: this, slot: &QQuickWebView::onFocusRequest);
103 connect(sender: m_webView, signal: &QWebView::javaScriptResult, receiver: this, slot: &QQuickWebView::onRunJavaScriptResult);
104 connect(sender: m_webView, signal: &QWebView::httpUserAgentChanged, receiver: this, slot: &QQuickWebView::httpUserAgentChanged);
105}
106
107QQuickWebView::~QQuickWebView()
108{
109}
110
111/*!
112 \qmlproperty url QtWebView::WebView::httpUserAgent
113 \since QtWebView 1.14
114 The user agent in use.
115
116 \note on WinRT, this property affects all WebViews of the application.
117*/
118
119void QQuickWebView::setHttpUserAgent(const QString &userAgent)
120{
121 m_webView->setHttpUserAgent(userAgent);
122}
123
124QString QQuickWebView::httpUserAgent() const
125{
126 return m_webView->httpUserAgent();
127}
128
129/*!
130 \qmlproperty url QtWebView::WebView::url
131
132 The URL of currently loaded web page. Changing this will trigger
133 loading new content.
134
135 The URL is used as-is. URLs that originate from user input should
136 be parsed with QUrl::fromUserInput().
137
138 \note The WebView does not support loading content through the Qt Resource system.
139*/
140
141void QQuickWebView::setUrl(const QUrl &url)
142{
143 m_webView->setUrl(url);
144}
145
146/*!
147 \qmlproperty string QtWebView::WebView::title
148 \readonly
149
150 The title of the currently loaded web page.
151*/
152
153QString QQuickWebView::title() const
154{
155 return m_webView->title();
156}
157
158QUrl QQuickWebView::url() const
159{
160 return m_webView->url();
161}
162
163/*!
164 \qmlproperty bool QtWebView::WebView::canGoBack
165 \readonly
166
167 Holds \c true if it's currently possible to navigate back in the web history.
168*/
169
170bool QQuickWebView::canGoBack() const
171{
172 return m_webView->canGoBack();
173}
174
175/*!
176 \qmlproperty bool QtWebView::WebView::canGoForward
177 \readonly
178
179 Holds \c true if it's currently possible to navigate forward in the web history.
180*/
181
182bool QQuickWebView::canGoForward() const
183{
184 return m_webView->canGoForward();
185}
186
187/*!
188 \qmlproperty int QtWebView::WebView::loadProgress
189 \readonly
190
191 The current load progress of the web content, represented as
192 an integer between 0 and 100.
193*/
194int QQuickWebView::loadProgress() const
195{
196 return m_webView->loadProgress();
197}
198
199/*!
200 \qmlproperty bool QtWebView::WebView::loading
201 \readonly
202
203 Holds \c true if the WebView is currently in the process of loading
204 new content, \c false otherwise.
205
206 \sa loadingChanged()
207*/
208
209/*!
210 \qmlsignal QtWebView::WebView::loadingChanged(WebViewLoadRequest loadRequest)
211
212 This signal is emitted when the state of loading the web content changes.
213 By handling this signal it's possible, for example, to react to page load
214 errors.
215
216 The \a loadRequest parameter holds the \e url and \e status of the request,
217 as well as an \e errorString containing an error message for a failed
218 request.
219
220 \sa WebViewLoadRequest
221*/
222bool QQuickWebView::isLoading() const
223{
224 return m_webView->isLoading();
225}
226
227/*!
228 \qmlmethod void QtWebView::WebView::goBack()
229
230 Navigates back in the web history.
231*/
232void QQuickWebView::goBack()
233{
234 m_webView->goBack();
235}
236
237/*!
238 \qmlmethod void QtWebView::WebView::goForward()
239
240 Navigates forward in the web history.
241*/
242void QQuickWebView::goForward()
243{
244 m_webView->goForward();
245}
246
247/*!
248 \qmlmethod void QtWebView::WebView::reload()
249
250 Reloads the current \l url.
251*/
252void QQuickWebView::reload()
253{
254 m_webView->reload();
255}
256
257/*!
258 \qmlmethod void QtWebView::WebView::stop()
259
260 Stops loading the current \l url.
261*/
262void QQuickWebView::stop()
263{
264 m_webView->stop();
265}
266
267/*!
268 \qmlmethod void QtWebView::WebView::loadHtml(string html, url baseUrl)
269
270 Loads the specified \a html content to the web view.
271
272 This method offers a lower-level alternative to the \l url property,
273 which references HTML pages via URL.
274
275 External objects such as stylesheets or images referenced in the HTML
276 document should be located relative to \a baseUrl. For example, if \a html
277 is retrieved from \c http://www.example.com/documents/overview.html, which
278 is the base URL, then an image referenced with the relative url, \c diagram.png,
279 should be at \c{http://www.example.com/documents/diagram.png}.
280
281 \note The WebView does not support loading content through the Qt Resource system.
282
283 \sa url
284*/
285void QQuickWebView::loadHtml(const QString &html, const QUrl &baseUrl)
286{
287 m_webView->loadHtml(html, baseUrl);
288}
289
290/*!
291 \qmlmethod void QtWebView::WebView::runJavaScript(string script, variant callback)
292
293 Runs the specified JavaScript.
294 In case a \a callback function is provided, it will be invoked after the \a script
295 finished running.
296
297 \badcode
298 runJavaScript("document.title", function(result) { console.log(result); });
299 \endcode
300*/
301void QQuickWebView::runJavaScript(const QString &script, const QJSValue &callback)
302{
303 const int callbackId = callback.isCallable() ? callbacks->insertCallback(callback)
304 : -1;
305 runJavaScriptPrivate(script, callbackId);
306}
307
308void QQuickWebView::runJavaScriptPrivate(const QString &script, int callbackId)
309{
310 m_webView->runJavaScriptPrivate(script, callbackId);
311}
312
313void QQuickWebView::itemChange(ItemChange change, const ItemChangeData &value)
314{
315 if (change == QQuickItem::ItemActiveFocusHasChanged) {
316 m_webView->setFocus(value.boolValue);
317 }
318 QQuickItem::itemChange(change, value);
319}
320
321void QQuickWebView::onRunJavaScriptResult(int id, const QVariant &variant)
322{
323 if (id == -1)
324 return;
325
326 QJSValue callback = callbacks->takeCallback(callbackId: id);
327 if (callback.isUndefined())
328 return;
329
330 QQmlEngine *engine = qmlEngine(this);
331 if (engine == 0) {
332 qWarning(msg: "No JavaScript engine, unable to handle JavaScript callback!");
333 return;
334 }
335
336 QJSValueList args;
337 args.append(t: engine->toScriptValue(value: variant));
338 callback.call(args);
339}
340
341void QQuickWebView::onFocusRequest(bool focus)
342{
343 setFocus(focus);
344}
345
346void QQuickWebView::onLoadingChanged(const QWebViewLoadRequestPrivate &loadRequest)
347{
348 QQuickWebViewLoadRequest qqLoadRequest(loadRequest);
349 Q_EMIT loadingChanged(loadRequest: &qqLoadRequest);
350}
351
352QJSValue QQuickWebView::takeCallback(int id)
353{
354 return callbacks->takeCallback(callbackId: id);
355}
356

source code of qtwebview/src/webview/qquickwebview.cpp