summaryrefslogtreecommitdiffstats
path: root/src/core/api/qwebengineurlscheme.cpp
blob: 4af89c616818e185a85bf33817464a60ed8a477d (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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
// Copyright (C) 2018 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 "qwebengineurlscheme.h"

#include "url/url_util_qt.h"

#include <QtDebug>

QT_BEGIN_NAMESPACE

ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::Syntax::Path, url::SCHEME_WITHOUT_AUTHORITY)
ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::Syntax::Host, url::SCHEME_WITH_HOST)
ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::Syntax::HostAndPort, url::SCHEME_WITH_HOST_AND_PORT)
ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::Syntax::HostPortAndUserInformation, url::SCHEME_WITH_HOST_PORT_AND_USER_INFORMATION)

ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::PortUnspecified, url::PORT_UNSPECIFIED)

ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::SecureScheme, url::CustomScheme::Secure)
ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::LocalScheme, url::CustomScheme::Local)
ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::LocalAccessAllowed, url::CustomScheme::LocalAccessAllowed)
ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::NoAccessAllowed, url::CustomScheme::NoAccessAllowed)
ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::ServiceWorkersAllowed, url::CustomScheme::ServiceWorkersAllowed)
ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::ViewSourceAllowed, url::CustomScheme::ViewSourceAllowed)
ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::ContentSecurityPolicyIgnored, url::CustomScheme::ContentSecurityPolicyIgnored)
ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::CorsEnabled, url::CustomScheme::CorsEnabled)

static bool g_schemesLocked = false;

class QWebEngineUrlSchemePrivate : public QSharedData
                                 , public url::CustomScheme
{
public:
    QWebEngineUrlSchemePrivate() {}
    QWebEngineUrlSchemePrivate(const url::CustomScheme &cs) : url::CustomScheme(cs) {}
    static QSharedDataPointer<QWebEngineUrlSchemePrivate> defaultConstructed()
    {
        static QSharedDataPointer<QWebEngineUrlSchemePrivate> instance(new QWebEngineUrlSchemePrivate);
        return instance;
    }
};

/*!
  \class QWebEngineUrlScheme
  \inmodule QtWebEngineCore
  \since 5.12
  \brief The QWebEngineUrlScheme class configures a custom URL scheme.

  A web engine URL scheme describes a URL scheme from the web engine's
  perspective, specifying how URLs of this scheme should be parsed, and which
  security restrictions should be placed on resources originating from such
  URLs.

  Custom URL schemes must be configured early at application startup, before
  creating any \QWE classes. In general this means the schemes need to be configured before
  a QGuiApplication or QApplication instance is created.

  Every registered scheme configuration applies globally to all profiles.

  \code
  int main(int argc, char **argv)
  {
      QWebEngineUrlScheme scheme("myscheme");
      scheme.setSyntax(QWebEngineUrlScheme::Syntax::HostAndPort);
      scheme.setDefaultPort(2345);
      scheme.setFlags(QWebEngineUrlScheme::SecureScheme);
      QWebEngineUrlScheme::registerScheme(scheme);
      ...
  }
  \endcode

  To actually make use of the custom URL scheme, a \l QWebEngineUrlSchemeHandler
  must be created and registered in a profile.

  \sa QWebEngineUrlSchemeHandler
*/

/*!
  \enum QWebEngineUrlScheme::Syntax

  This enum type lists types of URL syntax.

  To apply the same-origin policy to a custom URL scheme, WebEngine must be able
  to compute the origin (host and port combination) of a URL. The \c {Host...}
  options indicate that the URL scheme conforms to the standard URL syntax (like
  \c http) and automatically enable the same-origin policy. The \c {Path}
  option indicates that the URL scheme uses a non-standard syntax and that the
  same-origin policy cannot be applied.

  \value HostPortAndUserInformation
  The authority component of a URL of this type has all of the standard
  elements: host, port, user name, and password. A URL without a port will use
  the \l defaultPort (which \e must not be \l PortUnspecified).

  \value HostAndPort
  The authority component of a URL of this type has only the host and port
  elements. A URL without a port will use the \l defaultPort (which \e must not
  be \l PortUnspecified).

  \value Host
  The authority component of a URL of this type has only the host part and no
  port. The \l defaultPort \e must be set to \l PortUnspecified.

  \value Path
  A URL of this type has no authority component at all. Everything after scheme
  name and separator character (:) will be preserved as is without validation
  or canonicalization. All URLs of such a scheme will be considered as having
  the same origin (unless the \c NoAccessAllowed flag is used).
*/

/*!
  \enum QWebEngineUrlScheme::SpecialPort

  This enum type defines special values for \l defaultPort.

  \value PortUnspecified
  Indicates that the URL scheme does not have a port element.
*/

/*!
  \enum QWebEngineUrlScheme::Flag

  This enum type specifies security options that should apply to a URL scheme.

  \value SecureScheme
  Indicates that the URL scheme is
  \l{https://www.w3.org/TR/powerful-features/#is-origin-trustworthy}{potentially
  trustworthy}. This flag should only be applied to URL schemes which ensure
  data authenticity, confidentiality, and integrity, either through encryption
  or other means. Examples of secure builtin schemes include \c https
  (authenticated and encrypted) and \c qrc (local resources only), whereas \c
  http is an example of an insecure scheme.

  \value LocalScheme
  Indicates that the URL scheme provides access to local resources. The purpose
  of this flag is to prevent network content from accessing local resources.
  Only schemes with the \c LocalAccessAllowed flag may load resources from a
  scheme with the \c LocalScheme flag. The only builtin scheme with this flag is \c
  file.

  \value LocalAccessAllowed
  Indicates that content from this scheme should be allowed to load resources
  from schemes with the \c LocalScheme flag.

  \value NoAccessAllowed
  Indicates that all content from this scheme should be forced to have unique
  opaque origins: no two resources will have the same origin.

  \value ServiceWorkersAllowed
  Indicates that the Service Workers API should be enabled.

  \value ViewSourceAllowed
  Indicates that the View Source feature should be enabled.

  \value ContentSecurityPolicyIgnored
  Indicates that accesses to this scheme should bypass all
  Content-Security-Policy checks.

  \value CorsEnabled
  Enables cross-origin resource sharing (CORS) for this scheme. This flag is
  required in order for content to be loaded by documents of a different origin,
  this includes access from other schemes. The appropriate CORS headers are
  generated automatically by the QWebEngineUrlRequestJob class. By default only
  \c http and \c https are CORS enabled. (Added in Qt 5.14)
*/

QWebEngineUrlScheme::QWebEngineUrlScheme(QWebEngineUrlSchemePrivate *d) : d(d) {}

/*!
  Constructs a web engine URL scheme with default values.
*/
QWebEngineUrlScheme::QWebEngineUrlScheme()
    : QWebEngineUrlScheme(QWebEngineUrlSchemePrivate::defaultConstructed())
{
}

/*!
  Constructs a web engine URL scheme with given \a name.
*/
QWebEngineUrlScheme::QWebEngineUrlScheme(const QByteArray &name)
    : QWebEngineUrlScheme()
{
    setName(name);
}

/*!
  Copies \a that.
*/
QWebEngineUrlScheme::QWebEngineUrlScheme(const QWebEngineUrlScheme &that) = default;

/*!
  Copies \a that.
*/
QWebEngineUrlScheme &QWebEngineUrlScheme::operator=(const QWebEngineUrlScheme &that) = default;

/*!
  Moves \a that.
*/
QWebEngineUrlScheme::QWebEngineUrlScheme(QWebEngineUrlScheme &&that) = default;

/*!
  Moves \a that.
*/
QWebEngineUrlScheme &QWebEngineUrlScheme::operator=(QWebEngineUrlScheme &&that) = default;

/*!
  Destructs this object.
*/
QWebEngineUrlScheme::~QWebEngineUrlScheme() = default;

/*!
  Returns \c true if this and \a that object are equal.
*/
bool QWebEngineUrlScheme::operator==(const QWebEngineUrlScheme &that) const
{
    return (d == that.d)
        || (d->name == that.d->name
            && d->type == that.d->type
            && d->default_port == that.d->default_port
            && d->flags == that.d->flags);
}

/*!
  \fn bool QWebEngineUrlScheme::operator!=(const QWebEngineUrlScheme &that) const

  Returns \c true if this and \a that object are not equal.
*/

/*!
  Returns the name of this URL scheme.

  The default value is an empty string.

  \sa setName()
*/
QByteArray QWebEngineUrlScheme::name() const
{
    return QByteArray::fromStdString(d->name);
}

/*!
  Sets the name of this URL scheme to \a newValue.

  \note The name is automatically converted to lower case.

  \sa name()
*/
void QWebEngineUrlScheme::setName(const QByteArray &newValue)
{
    d->name = newValue.toLower().toStdString();
}

/*!
  Returns the syntax type of this URL scheme.

  The default value is \c Path.

  \sa Syntax, setSyntax()
*/
QWebEngineUrlScheme::Syntax QWebEngineUrlScheme::syntax() const
{
    return static_cast<Syntax>(d->type);
}

/*!
  Sets the syntax type of this URL scheme to \a newValue.

  \sa Syntax, syntax()
*/
void QWebEngineUrlScheme::setSyntax(Syntax newValue)
{
    d->type = static_cast<url::SchemeType>(newValue);
}

/*!
  Returns the default port of this URL scheme.

  The default value is \c PortUnspecified.

  \sa setDefaultPort()
*/
int QWebEngineUrlScheme::defaultPort() const
{
    return d->default_port;
}

/*!
  Sets the default port of this URL scheme to \a newValue.

  \sa defaultPort()
*/
void QWebEngineUrlScheme::setDefaultPort(int newValue)
{
    d->default_port = newValue;
}

/*!
  Returns the flags for this URL scheme.

  The default value is an empty set of flags.

  \sa Flags, setFlags()
*/
QWebEngineUrlScheme::Flags QWebEngineUrlScheme::flags() const
{
    return Flags(d->flags);
}

/*!
  Sets the flags for this URL scheme to \a newValue.

  \sa Flags, flags()
*/
void QWebEngineUrlScheme::setFlags(Flags newValue)
{
    d->flags = newValue;
}

/*!
  Registers \a scheme with the web engine's URL parser and security model.

  It is recommended that all custom URL schemes are first registered with this
  function at application startup, even if the default options are to be used.

  \warning This function must be called early at application startup, before
  creating any WebEngine classes. Late calls will be ignored.

  \sa schemeByName()
*/
void QWebEngineUrlScheme::registerScheme(const QWebEngineUrlScheme &scheme)
{
    if (scheme.d->name.empty()) {
        qWarning() << "QWebEngineUrlScheme::registerScheme: Scheme name cannot be empty";
        return;
    }

    bool needsPort = scheme.d->has_port_component();
    bool hasPort = scheme.d->default_port != url::PORT_UNSPECIFIED;
    if (needsPort && !hasPort) {
        qWarning() << "QWebEngineUrlScheme::registerScheme: Scheme" << scheme.name() << "needs a default port";
        return;
    }

    if (url::CustomScheme::FindScheme(scheme.d->name)) {
        qWarning() << "QWebEngineUrlScheme::registerScheme: Scheme" << scheme.name() << "already registered";
        return;
    }

    if (url::IsStandard(scheme.d->name.data(), url::Component(0, static_cast<int>(scheme.d->name.size())))) {
        qWarning() << "QWebEngineUrlScheme::registerScheme: Scheme" << scheme.name() << "is a standard scheme";
        return;
    }

    if (g_schemesLocked) {
        qWarning() << "QWebEngineUrlScheme::registerScheme: Too late to register scheme" << scheme.name();
        return;
    }

    url::CustomScheme::AddScheme(*scheme.d);
}

/*!
  Returns the web engine URL scheme with the given \a name or the
  default-constructed scheme.

  \sa registerScheme()
*/
QWebEngineUrlScheme QWebEngineUrlScheme::schemeByName(const QByteArray &name)
{
    base::StringPiece namePiece{ name.data(), static_cast<size_t>(name.size()) };
    if (const url::CustomScheme *cs = url::CustomScheme::FindScheme(namePiece))
        return QWebEngineUrlScheme(new QWebEngineUrlSchemePrivate(*cs));
    return QWebEngineUrlScheme();
}

void QWebEngineUrlScheme::lockSchemes()
{
    g_schemesLocked = true;
}

QT_END_NAMESPACE

#include "moc_qwebengineurlscheme.cpp"