2
* Copyright (C) 2010 Apple Inc. All Rights Reserved.
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
7
* 1. Redistributions of source code must retain the above copyright
8
* notice, this list of conditions and the following disclaimer.
9
* 2. Redistributions in binary form must reproduce the above copyright
10
* notice, this list of conditions and the following disclaimer in the
11
* documentation and/or other materials provided with the distribution.
13
* THIS SOFTWARE IS PROVIDED BY APPLE, INC. ``AS IS'' AND ANY
14
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
#include "LegacySchemeRegistry.h"
29
#include "RuntimeApplicationChecks.h"
31
#include <wtf/Locker.h>
32
#include <wtf/MainThread.h>
33
#include <wtf/NeverDestroyed.h>
34
#include <wtf/URLParser.h>
36
#if ENABLE(CONTENT_FILTERING)
37
#include "ContentFilter.h"
40
#include "QuickLook.h"
45
// FIXME: URLSchemesMap is a peculiar type name given that it is a set.
47
static const URLSchemesMap& builtinLocalURLSchemes();
48
static const Vector<String>& builtinSecureSchemes();
49
static const Vector<String>& builtinSchemesWithUniqueOrigins();
50
static const Vector<String>& builtinEmptyDocumentSchemes();
51
static const Vector<String>& builtinCanDisplayOnlyIfCanRequestSchemes();
52
static const Vector<String>& builtinCORSEnabledSchemes();
54
using StringVectorFunction = const Vector<String>& (*)();
56
static void add(URLSchemesMap& set, StringVectorFunction function)
58
for (auto& scheme : function())
62
static NeverDestroyed<URLSchemesMap> makeNeverDestroyedSchemeSet(const Vector<String>& (*function)())
69
static Lock schemeRegistryLock;
71
static const URLSchemesMap& allBuiltinSchemes()
73
static const auto schemes = makeNeverDestroyed([] {
74
static const StringVectorFunction functions[] {
76
builtinSchemesWithUniqueOrigins,
77
builtinEmptyDocumentSchemes,
78
builtinCanDisplayOnlyIfCanRequestSchemes,
79
builtinCORSEnabledSchemes,
82
// Other misc schemes that the LegacySchemeRegistry doesn't know about.
83
static const char* const otherSchemes[] = {
91
#if ENABLE(CONTENT_FILTERING)
92
ContentFilter::urlScheme(),
98
Locker<Lock> locker(schemeRegistryLock);
99
for (auto& scheme : builtinLocalURLSchemes())
102
for (auto& function : functions)
105
for (auto& scheme : otherSchemes)
112
static const URLSchemesMap& builtinLocalURLSchemes()
114
ASSERT(schemeRegistryLock.isHeld());
115
static const auto schemes = makeNeverDestroyed(URLSchemesMap {
124
static URLSchemesMap& localURLSchemes()
126
ASSERT(schemeRegistryLock.isHeld());
127
static NeverDestroyed<URLSchemesMap> localSchemes = builtinLocalURLSchemes();
131
static URLSchemesMap& displayIsolatedURLSchemes()
133
ASSERT(schemeRegistryLock.isHeld());
134
static NeverDestroyed<URLSchemesMap> displayIsolatedSchemes;
135
return displayIsolatedSchemes;
138
const Vector<String>& builtinSecureSchemes()
140
ASSERT(schemeRegistryLock.isHeld());
141
static const auto schemes = makeNeverDestroyed(Vector<String> {
146
#if PLATFORM(GTK) || PLATFORM(WPE)
153
static URLSchemesMap& secureSchemes()
155
ASSERT(schemeRegistryLock.isHeld());
156
static auto secureSchemes = makeNeverDestroyedSchemeSet(builtinSecureSchemes);
157
return secureSchemes;
160
const Vector<String>& builtinSchemesWithUniqueOrigins()
162
ASSERT(schemeRegistryLock.isHeld());
163
static const auto schemes = makeNeverDestroyed(Vector<String> {
166
// This is an intentional difference from the behavior the HTML specification calls for.
167
// See https://bugs.webkit.org/show_bug.cgi?id=11885
173
static URLSchemesMap& schemesWithUniqueOrigins()
175
ASSERT(schemeRegistryLock.isHeld());
176
static auto schemesWithUniqueOrigins = makeNeverDestroyedSchemeSet(builtinSchemesWithUniqueOrigins);
177
return schemesWithUniqueOrigins;
180
const Vector<String>& builtinEmptyDocumentSchemes()
182
ASSERT(isMainThread());
183
static const auto schemes = makeNeverDestroyed(Vector<String> { "about" });
187
static URLSchemesMap& emptyDocumentSchemes()
189
ASSERT(isMainThread());
190
static auto emptyDocumentSchemes = makeNeverDestroyedSchemeSet(builtinEmptyDocumentSchemes);
191
return emptyDocumentSchemes;
194
static URLSchemesMap& schemesForbiddenFromDomainRelaxation()
196
ASSERT(isMainThread());
197
static NeverDestroyed<URLSchemesMap> schemes;
201
const Vector<String>& builtinCanDisplayOnlyIfCanRequestSchemes()
203
ASSERT(schemeRegistryLock.isHeld());
204
static const auto schemes = makeNeverDestroyed(Vector<String> { "blob" });
208
static URLSchemesMap& canDisplayOnlyIfCanRequestSchemes()
210
ASSERT(!isInNetworkProcess());
211
ASSERT(schemeRegistryLock.isHeld());
212
static auto canDisplayOnlyIfCanRequestSchemes = makeNeverDestroyedSchemeSet(builtinCanDisplayOnlyIfCanRequestSchemes);
213
return canDisplayOnlyIfCanRequestSchemes;
216
static URLSchemesMap& notAllowingJavascriptURLsSchemes()
218
ASSERT(isMainThread());
219
static NeverDestroyed<URLSchemesMap> notAllowingJavascriptURLsSchemes;
220
return notAllowingJavascriptURLsSchemes;
223
void LegacySchemeRegistry::registerURLSchemeAsLocal(const String& scheme)
228
Locker<Lock> locker(schemeRegistryLock);
229
localURLSchemes().add(scheme);
232
void LegacySchemeRegistry::removeURLSchemeRegisteredAsLocal(const String& scheme)
234
Locker<Lock> locker(schemeRegistryLock);
235
if (builtinLocalURLSchemes().contains(scheme))
238
localURLSchemes().remove(scheme);
241
static URLSchemesMap& schemesAllowingDatabaseAccessInPrivateBrowsing()
243
ASSERT(isMainThread());
244
static NeverDestroyed<URLSchemesMap> schemesAllowingDatabaseAccessInPrivateBrowsing;
245
return schemesAllowingDatabaseAccessInPrivateBrowsing;
248
const Vector<String>& builtinCORSEnabledSchemes()
250
ASSERT(isMainThread());
251
static const auto schemes = makeNeverDestroyed(Vector<String> { "http", "https" });
255
static URLSchemesMap& CORSEnabledSchemes()
257
ASSERT(isMainThread());
258
// FIXME: http://bugs.webkit.org/show_bug.cgi?id=77160
259
static auto schemes = makeNeverDestroyedSchemeSet(builtinCORSEnabledSchemes);
263
static URLSchemesMap& ContentSecurityPolicyBypassingSchemes()
265
ASSERT(schemeRegistryLock.isHeld());
266
static NeverDestroyed<URLSchemesMap> schemes;
270
static URLSchemesMap& cachePartitioningSchemes()
272
ASSERT(schemeRegistryLock.isHeld());
273
static NeverDestroyed<URLSchemesMap> schemes;
277
static URLSchemesMap& serviceWorkerSchemes()
279
ASSERT(schemeRegistryLock.isHeld());
280
static NeverDestroyed<URLSchemesMap> schemes;
284
static URLSchemesMap& alwaysRevalidatedSchemes()
286
ASSERT(isMainThread());
287
static NeverDestroyed<URLSchemesMap> schemes;
291
bool LegacySchemeRegistry::shouldTreatURLSchemeAsLocal(const String& scheme)
296
Locker<Lock> locker(schemeRegistryLock);
297
return localURLSchemes().contains(scheme);
300
void LegacySchemeRegistry::registerURLSchemeAsNoAccess(const String& scheme)
305
Locker<Lock> locker(schemeRegistryLock);
306
schemesWithUniqueOrigins().add(scheme);
309
bool LegacySchemeRegistry::shouldTreatURLSchemeAsNoAccess(const String& scheme)
314
Locker<Lock> locker(schemeRegistryLock);
315
return schemesWithUniqueOrigins().contains(scheme);
318
void LegacySchemeRegistry::registerURLSchemeAsDisplayIsolated(const String& scheme)
323
Locker<Lock> locker(schemeRegistryLock);
324
displayIsolatedURLSchemes().add(scheme);
327
bool LegacySchemeRegistry::shouldTreatURLSchemeAsDisplayIsolated(const String& scheme)
332
Locker<Lock> locker(schemeRegistryLock);
333
return displayIsolatedURLSchemes().contains(scheme);
336
void LegacySchemeRegistry::registerURLSchemeAsSecure(const String& scheme)
341
Locker<Lock> locker(schemeRegistryLock);
342
secureSchemes().add(scheme);
345
bool LegacySchemeRegistry::shouldTreatURLSchemeAsSecure(const String& scheme)
350
Locker<Lock> locker(schemeRegistryLock);
351
return secureSchemes().contains(scheme);
354
void LegacySchemeRegistry::registerURLSchemeAsEmptyDocument(const String& scheme)
358
emptyDocumentSchemes().add(scheme);
361
bool LegacySchemeRegistry::shouldLoadURLSchemeAsEmptyDocument(const String& scheme)
363
return !scheme.isNull() && emptyDocumentSchemes().contains(scheme);
366
void LegacySchemeRegistry::setDomainRelaxationForbiddenForURLScheme(bool forbidden, const String& scheme)
372
schemesForbiddenFromDomainRelaxation().add(scheme);
374
schemesForbiddenFromDomainRelaxation().remove(scheme);
377
bool LegacySchemeRegistry::isDomainRelaxationForbiddenForURLScheme(const String& scheme)
379
return !scheme.isNull() && schemesForbiddenFromDomainRelaxation().contains(scheme);
382
bool LegacySchemeRegistry::canDisplayOnlyIfCanRequest(const String& scheme)
384
ASSERT(!isInNetworkProcess());
388
Locker<Lock> locker(schemeRegistryLock);
389
return canDisplayOnlyIfCanRequestSchemes().contains(scheme);
392
void LegacySchemeRegistry::registerAsCanDisplayOnlyIfCanRequest(const String& scheme)
394
ASSERT(!isInNetworkProcess());
398
Locker<Lock> locker(schemeRegistryLock);
399
canDisplayOnlyIfCanRequestSchemes().add(scheme);
402
void LegacySchemeRegistry::registerURLSchemeAsNotAllowingJavascriptURLs(const String& scheme)
406
notAllowingJavascriptURLsSchemes().add(scheme);
409
bool LegacySchemeRegistry::shouldTreatURLSchemeAsNotAllowingJavascriptURLs(const String& scheme)
411
return !scheme.isNull() && notAllowingJavascriptURLsSchemes().contains(scheme);
414
void LegacySchemeRegistry::registerURLSchemeAsAllowingDatabaseAccessInPrivateBrowsing(const String& scheme)
418
schemesAllowingDatabaseAccessInPrivateBrowsing().add(scheme);
421
bool LegacySchemeRegistry::allowsDatabaseAccessInPrivateBrowsing(const String& scheme)
423
return !scheme.isNull() && schemesAllowingDatabaseAccessInPrivateBrowsing().contains(scheme);
426
void LegacySchemeRegistry::registerURLSchemeAsCORSEnabled(const String& scheme)
428
ASSERT(!isInNetworkProcess());
431
CORSEnabledSchemes().add(scheme);
434
bool LegacySchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(const String& scheme)
436
ASSERT(!isInNetworkProcess());
437
return !scheme.isNull() && CORSEnabledSchemes().contains(scheme);
440
Vector<String> LegacySchemeRegistry::allURLSchemesRegisteredAsCORSEnabled()
442
ASSERT(!isInNetworkProcess());
443
return copyToVector(CORSEnabledSchemes());
446
void LegacySchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme)
451
Locker<Lock> locker(schemeRegistryLock);
452
ContentSecurityPolicyBypassingSchemes().add(scheme);
455
void LegacySchemeRegistry::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(const String& scheme)
460
Locker<Lock> locker(schemeRegistryLock);
461
ContentSecurityPolicyBypassingSchemes().remove(scheme);
464
bool LegacySchemeRegistry::schemeShouldBypassContentSecurityPolicy(const String& scheme)
469
Locker<Lock> locker(schemeRegistryLock);
470
return ContentSecurityPolicyBypassingSchemes().contains(scheme);
473
void LegacySchemeRegistry::registerURLSchemeAsAlwaysRevalidated(const String& scheme)
477
alwaysRevalidatedSchemes().add(scheme);
480
bool LegacySchemeRegistry::shouldAlwaysRevalidateURLScheme(const String& scheme)
482
return !scheme.isNull() && alwaysRevalidatedSchemes().contains(scheme);
485
void LegacySchemeRegistry::registerURLSchemeAsCachePartitioned(const String& scheme)
490
Locker<Lock> locker(schemeRegistryLock);
491
cachePartitioningSchemes().add(scheme);
494
bool LegacySchemeRegistry::shouldPartitionCacheForURLScheme(const String& scheme)
499
Locker<Lock> locker(schemeRegistryLock);
500
return cachePartitioningSchemes().contains(scheme);
503
void LegacySchemeRegistry::registerURLSchemeServiceWorkersCanHandle(const String& scheme)
508
Locker<Lock> locker(schemeRegistryLock);
509
serviceWorkerSchemes().add(scheme);
512
bool LegacySchemeRegistry::canServiceWorkersHandleURLScheme(const String& scheme)
517
if (scheme.startsWithIgnoringASCIICase("http"_s)) {
518
if (scheme.length() == 4)
520
if (scheme.length() == 5 && isASCIIAlphaCaselessEqual(scheme[4], 's'))
524
Locker<Lock> locker(schemeRegistryLock);
525
return serviceWorkerSchemes().contains(scheme);
528
bool LegacySchemeRegistry::isServiceWorkerContainerCustomScheme(const String& scheme)
530
Locker<Lock> locker(schemeRegistryLock);
531
return !scheme.isNull() && serviceWorkerSchemes().contains(scheme);
534
bool LegacySchemeRegistry::isUserExtensionScheme(const String& scheme)
536
// FIXME: Remove this once Safari has adopted WKWebViewConfiguration._corsDisablingPatterns
538
if (scheme == "safari-extension")
541
UNUSED_PARAM(scheme);
546
bool LegacySchemeRegistry::isBuiltinScheme(const String& scheme)
548
return !scheme.isNull() && (allBuiltinSchemes().contains(scheme) || WTF::URLParser::isSpecialScheme(scheme));
551
} // namespace WebCore