summaryrefslogtreecommitdiffstats
path: root/src/core/api/qwebengineframe.cpp
blob: 1eedc4b9254a732b580b2ca8e190dcee892f3386 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

#include "qwebengineframe.h"

#include "qwebenginescript.h"
#include <QtQml/qqmlengine.h>

#include "web_contents_adapter_client.h"
#include "web_contents_adapter.h"

QT_BEGIN_NAMESPACE

/*!
    \class QWebEngineFrame
    \brief The QWebEngineFrame class gives information about and control over a page frame.
    \since 6.8

    \inmodule QtWebEngineCore

    A web engine frame represents a single frame within a web page, such as those created by
    \c <frame> or \c <iframe> HTML elements.
    An active QWebEnginePage has one or more frames arranged in a tree structure. The top-level
    frame, the root of this tree, can be accessed through the mainFrame() method, and
    children() provides a frame's direct descendants.

    A frame's lifetime is, at most, as long as the QWebEnginePage object that produced it.
    However, frames may be created and deleted spontaneously and dynamically, for example through
    navigation and script execution. Because of this, many QWebEngineFrame methods return
    optional values, which will be \c std::nullopt if the frame no longer exists.
*/

/*! \internal
 */
QWebEngineFrame::QWebEngineFrame(QtWebEngineCore::WebContentsAdapterClient *adapter, quint64 id)
    : m_adapterClient(adapter), m_id(id)
{
}

/*!
    Returns \c{true} if this object represents an existing frame; \c{false} otherwise.

    Once a frame is invalid, it never becomes valid again.
*/
bool QWebEngineFrame::isValid() const
{
    return m_adapterClient->webContentsAdapter()->hasFrame(m_id);
}

/*!
    Returns the frame name; that is, what would be returned by \c window.name in JavaScript.

    If the frame could not be found, returns a null QString.

    \sa htmlName
*/
QString QWebEngineFrame::name() const
{
    return m_adapterClient->webContentsAdapter()->frameName(m_id);
}

/*!
    Returns the value of the frame's \c name HTML attribute, or an empty string if it has none.

    If the frame could not be found, returns a null QString.

    \sa name
*/
QString QWebEngineFrame::htmlName() const
{
    return m_adapterClient->webContentsAdapter()->frameHtmlName(m_id);
}

/*!
    Returns a list of the frame's children in an arbitrary order.

    If the frame could not be found, returns an empty list.
 */
QList<QWebEngineFrame> QWebEngineFrame::children() const
{
    QList<QWebEngineFrame> result;
    for (auto childId : m_adapterClient->webContentsAdapter()->frameChildren(m_id))
        result.push_back(QWebEngineFrame{ m_adapterClient, childId });
    return result;
}

/*!
    Returns the URL of the content currently loaded in this frame.

    If the frame could not be found, returns an empty QUrl.
 */
QUrl QWebEngineFrame::url() const
{
    return m_adapterClient->webContentsAdapter()->frameUrl(m_id);
}

/*!
    Returns the size of the frame within the viewport.

    If the frame could not be found, returns QSizeF().
 */
QSizeF QWebEngineFrame::size() const
{
    return m_adapterClient->webContentsAdapter()->frameSize(m_id);
}

/*! \fn void QWebEngineFrame::runJavaScript(const QString &script, const std::function<void(const QVariant &)> &callback)
    \fn void QWebEngineFrame::runJavaScript(const QString &script, quint32 worldId)
    \fn void QWebEngineFrame::runJavaScript(const QString &script, quint32 worldId, const
   std::function<void(const QVariant &)> &callback)

    Runs the JavaScript code contained in \a script on this frame, without checking
    whether the DOM of the page has been constructed.
    To avoid conflicts with other scripts executed on the page, the world in
    which the script is run is specified by \a worldId. The world ID values are
    the same as provided by QWebEngineScript::ScriptWorldId, and between \c 0
    and \c 256. If you leave out the \c world ID, the script is run in the
    \c MainWorld.
    When the script has been executed, \a callback is called with the result of the last
    executed statement. \c callback can be any of a function pointer, a functor or a lambda,
    and it is expected to take a QVariant parameter. For example:
    \code
    page.runJavaScript("document.title", [](const QVariant &v) { qDebug() << v.toString(); });
    \endcode
    Only plain data can be returned from JavaScript as the result value.
    Supported data types include all of the JSON data types as well as, for
    example, \c{Date} and \c{ArrayBuffer}. Unsupported data types include, for
    example, \c{Function} and \c{Promise}.
    \warning Do not execute lengthy routines in the callback function, because it might block the
    rendering of the web engine page.
    \warning We guarantee that the \a callback is always called, but it might be
   done during page destruction. When QWebEnginePage is deleted, the callback is triggered with an
   invalid value and it is not safe to use the corresponding QWebEnginePage or QWebEngineView
   instance inside it.
    \sa QWebEngineScript::ScriptWorldId, QWebEnginePage::runJavaScript, {Script Injection}
 */
void QWebEngineFrame::runJavaScript(const QString &script,
                                    const std::function<void(const QVariant &)> &callback)
{
    runJavaScript(script, QWebEngineScript::MainWorld, callback);
}

void QWebEngineFrame::runJavaScript(const QString &script, quint32 worldId,
                                    const std::function<void(const QVariant &)> &callback)
{
    m_adapterClient->runJavaScript(script, worldId, m_id, callback);
}

void QWebEngineFrame::runJavaScript(const QString &script, quint32 worldId)
{
    runJavaScript(script, worldId, std::function<void(const QVariant &)>{});
}

void QWebEngineFrame::runJavaScript(const QString &script, const QJSValue &callback)
{
    runJavaScript(script, QWebEngineScript::MainWorld, callback);
}

void QWebEngineFrame::runJavaScript(const QString &script, quint32 worldId,
                                    const QJSValue &callback)
{
    std::function<void(const QVariant &)> wrappedCallback;
    if (!callback.isUndefined()) {
        const QObject *holdingObject = m_adapterClient->holdingQObject();
        wrappedCallback = [holdingObject, callback](const QVariant &result) {
            if (auto engine = qmlEngine(holdingObject)) {
                QJSValueList args;
                args.append(engine->toScriptValue(result));
                callback.call(args);
            } else {
                qWarning("No QML engine found to execute runJavaScript() callback");
            }
        };
    }
    runJavaScript(script, worldId, wrappedCallback);
}

/*! \fn bool QWebEngineFrame::operator==(const QWebEngineFrame &left, const QWebEngineFrame &right) noexcept

    Returns \c{true} if \a left and \a right represent the same frame in the same web page,
   otherwise \c{false}.
 */

/*! \fn bool QWebEngineFrame::operator!=(const QWebEngineFrame &left, const QWebEngineFrame &right) noexcept

    Returns \c{true} if \a left and \a right represent different frames in the same web page,
   otherwise \c{false}.
 */

QT_END_NAMESPACE

#include "moc_qwebengineframe.cpp"