Skip to content

Commit

Permalink
Introduce PublicSuffixStore with cache
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=271188
rdar://124971859

Reviewed by Per Arne Vollan and Chris Dumez.

Intoduce a new class PublicSuffixStore and move existing public suffix related functions into it. PublicSuffixStore can
have a cache for public suffix. When the cache is in use, PublicSuffixStore searches public suffix in it before invoking
platform specific code (this may help us to tighten sandbox in some process later). Currently the cache is only enabled
in web process on Cocoa platforms.

Before this patch, web process has a cache for finding top privately controlled domain of a given host. UI process sends
(host, domain) pair to web process on load time, and web process will add the entry in cache (256605@main). This patch
makes UI process send the public suffix the to web process, and makes web process store it in the new public suffix
cache, since the domain cache has a size limit, and it only benefits search for the given host. Also, this patch fixes
the regression from 270762@main, that web process does not update the cache on receiving LoadParameters (since
setTopPrivatelyControlledDomain is dropped from LoadParameters::decode), by adding addPublicSuffix to
WebPage::platformDidReceiveLoadParameters.

* Source/WebCore/Headers.cmake:
* Source/WebCore/Sources.txt:
* Source/WebCore/SourcesCocoa.txt:
* Source/WebCore/WebCore.xcodeproj/project.pbxproj:
* Source/WebCore/dom/Document.cpp:
(WebCore::Document::urlForBindings const):
* Source/WebCore/loader/ResourceLoadStatistics.cpp:
* Source/WebCore/loader/cache/MemoryCache.cpp:
* Source/WebCore/page/Quirks.cpp:
(WebCore::isYahooMail):
(WebCore::Quirks::shouldHideSearchFieldResultsButton const):
(WebCore::Quirks::isAmazon const):
(WebCore::Quirks::isGoogleMaps const):
* Source/WebCore/page/SecurityOrigin.cpp:
(WebCore::SecurityOrigin::isSameSiteAs const):
(WebCore::SecurityOrigin::isMatchingRegistrableDomainSuffix const):
* Source/WebCore/page/csp/ContentSecurityPolicySourceList.cpp:
(WebCore::ContentSecurityPolicySourceList::isValidSourceForExtensionMode):
* Source/WebCore/platform/Curl.cmake:
* Source/WebCore/platform/PublicSuffixStore.cpp: Added.
(WebCore::PublicSuffixStore::singleton):
(WebCore::PublicSuffixStore::clearHostTopPrivatelyControlledDomainCache):
(WebCore::PublicSuffixStore::isPublicSuffix const):
(WebCore::PublicSuffixStore::publicSuffix const):
(WebCore::PublicSuffixStore::topPrivatelyControlledDomain const):
* Source/WebCore/platform/PublicSuffixStore.h: Renamed from Source/WebCore/platform/PublicSuffix.h.
* Source/WebCore/platform/RegistrableDomain.h:
(WebCore::RegistrableDomain::uncheckedCreateFromHost):
(WebCore::RegistrableDomain::registrableDomainFromHost):
* Source/WebCore/platform/SourcesSoup.txt:
* Source/WebCore/platform/cocoa/PublicSuffixCocoa.mm: Removed.
* Source/WebCore/platform/cocoa/PublicSuffixStoreCocoa.mm: Added.
(WebCore::isPublicSuffixCF):
(WebCore::PublicSuffixStore::platformIsPublicSuffix const):
(WebCore::PublicSuffixStore::platformTopPrivatelyControlledDomain const):
(WebCore::PublicSuffixStore::enablePublicSuffixCache):
(WebCore::PublicSuffixStore::addPublicSuffix):
* Source/WebCore/platform/glib/UserAgentQuirks.cpp:
(WebCore::UserAgentQuirks::quirksForURL):
* Source/WebCore/platform/graphics/skia/PathSkia.cpp:
* Source/WebCore/platform/network/NetworkStorageSession.cpp:
* Source/WebCore/platform/network/ResourceRequestBase.cpp:
(WebCore::ResourceRequestBase::partitionName):
* Source/WebCore/platform/network/cf/NetworkStorageSessionCFNet.cpp:
* Source/WebCore/platform/network/cf/ResourceRequestCFNet.cpp:
* Source/WebCore/platform/network/curl/CookieJarDB.cpp:
(WebCore::CookieJarDB::hasCookies):
(WebCore::CookieJarDB::canAcceptCookie):
* Source/WebCore/platform/network/curl/PublicSuffixStoreCurl.cpp: Renamed from Source/WebCore/platform/network/curl/PublicSuffixCurl.cpp.
(WebCore::PublicSuffixStore::platformIsPublicSuffix const):
(WebCore::topPrivatelyControlledDomainInternal):
(WebCore::PublicSuffixStore::platformTopPrivatelyControlledDomain const):
* Source/WebCore/platform/soup/PublicSuffixStoreSoup.cpp: Renamed from Source/WebCore/platform/soup/PublicSuffixSoup.cpp.
(WebCore::PublicSuffixStore::platformIsPublicSuffix const):
(WebCore::permissiveTopPrivateDomain):
(WebCore::PublicSuffixStore::platformTopPrivatelyControlledDomain const):
* Source/WebKit/NetworkProcess/cocoa/NetworkProcessCocoa.mm:
* Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp:
(WebKit::NetworkDataTaskSoup::shouldAllowHSTSPolicySetting const):
* Source/WebKit/Shared/GoToBackForwardItemParameters.h:
* Source/WebKit/Shared/GoToBackForwardItemParameters.serialization.in:
* Source/WebKit/Shared/LoadParameters.h:
* Source/WebKit/Shared/LoadParameters.serialization.in:
* Source/WebKit/UIProcess/Extensions/Cocoa/WebExtensionMatchPatternCocoa.mm:
(WebKit::WebExtensionMatchPattern::hostIsPublicSuffix const):
* Source/WebKit/UIProcess/ProvisionalPageProxy.cpp:
(WebKit::ProvisionalPageProxy::goToBackForwardItem):
* Source/WebKit/UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::launchProcessForReload):
(WebKit::WebPageProxy::loadRequestWithNavigationShared):
(WebKit::WebPageProxy::loadFile):
(WebKit::WebPageProxy::goToBackForwardItem):
(WebKit::WebPageProxy::resetStateAfterProcessTermination):
* Source/WebKit/UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::processDidTerminateOrFailedToLaunch):
(WebKit::WebProcessProxy::didExceedMemoryFootprintThreshold):
* Source/WebKit/UIProcess/WebsiteData/WebsiteDataRecord.cpp:
(WebKit::WebsiteDataRecord::displayNameForHostName):
(WebKit::WebsiteDataRecord::displayNameForOrigin):
(WebKit::WebsiteDataRecord::topPrivatelyControlledDomain):
* Source/WebKit/WebProcess/WebPage/Cocoa/WebPageCocoa.mm:
(WebKit::WebPage::platformDidReceiveLoadParameters):
* Source/WebKit/WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::goToBackForwardItem):
* Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm:
(WebKit::prewarmLogs):
(WebKit::WebProcess::platformInitializeProcess):
* Tools/TestWebKitAPI/Tests/WebCore/PublicSuffix.cpp:
(TestWebKitAPI::TEST_F):

Canonical link: https://commits.webkit.org/276505@main
  • Loading branch information
szewai committed Mar 21, 2024
1 parent 915fa90 commit ac05e4c
Show file tree
Hide file tree
Showing 41 changed files with 436 additions and 319 deletions.
2 changes: 1 addition & 1 deletion Source/WebCore/Headers.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -1746,7 +1746,7 @@ set(WebCore_PRIVATE_FRAMEWORK_HEADERS
platform/ProcessIdentity.h
platform/ProcessQualified.h
platform/PromisedAttachmentInfo.h
platform/PublicSuffix.h
platform/PublicSuffixStore.h
platform/RectEdges.h
platform/ReferrerPolicy.h
platform/RegistrableDomain.h
Expand Down
1 change: 1 addition & 0 deletions Source/WebCore/Sources.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2127,6 +2127,7 @@ platform/PreviewConverter.cpp
platform/ProcessCapabilities.cpp
platform/ProcessIdentifier.cpp
platform/ProcessIdentity.cpp
platform/PublicSuffixStore.cpp
platform/ReferrerPolicy.cpp
platform/RemoteCommandListener.cpp
platform/RunLoopObserver.cpp
Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/SourcesCocoa.txt
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ platform/cocoa/PlatformPasteboardCocoa.mm
platform/cocoa/PlatformSpeechSynthesizerCocoa.mm @no-unify
platform/cocoa/PlaybackSessionModelMediaElement.mm
platform/cocoa/PowerSourceNotifier.mm
platform/cocoa/PublicSuffixCocoa.mm
platform/cocoa/PublicSuffixStoreCocoa.mm
platform/cocoa/RemoteCommandListenerCocoa.mm
platform/cocoa/RuntimeApplicationChecksCocoa.mm
platform/cocoa/SearchPopupMenuCocoa.mm
Expand Down
14 changes: 8 additions & 6 deletions Source/WebCore/WebCore.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@
/* Begin PBXBuildFile section */
0014628B103CD1DE000B20DB /* OriginAccessEntry.h in Headers */ = {isa = PBXBuildFile; fileRef = 00146289103CD1DE000B20DB /* OriginAccessEntry.h */; };
003F1FEA11E6AB43008258D9 /* UserContentTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 003F1FE911E6AB43008258D9 /* UserContentTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
0081FF0016B0A2D3008AAA7A /* PublicSuffix.h in Headers */ = {isa = PBXBuildFile; fileRef = 0081FEFD16B0A244008AAA7A /* PublicSuffix.h */; settings = {ATTRIBUTES = (Private, ); }; };
00B9318813BA8DBA0035A948 /* XMLDocumentParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 00B9318213BA867F0035A948 /* XMLDocumentParser.h */; };
00B9318C13BA8DCC0035A948 /* XMLDocumentParserScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 00B9318613BA867F0035A948 /* XMLDocumentParserScope.h */; };
00C60E3F13D76D7E0092A275 /* MarkupTokenizerInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 00C60E3E13D76D7E0092A275 /* MarkupTokenizerInlines.h */; };
Expand Down Expand Up @@ -1269,6 +1268,7 @@
3A18A2ED2AFEAA7C00DB976C /* MarkupExclusionRule.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A18A2EC2AFEAA7C00DB976C /* MarkupExclusionRule.h */; settings = {ATTRIBUTES = (Private, ); }; };
3A2FE8CF2978CC7800BA1D92 /* GCGLSpan.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A2FE8CE2978CC7800BA1D92 /* GCGLSpan.h */; settings = {ATTRIBUTES = (Private, ); }; };
3A3A05812B04973800017309 /* PlatformXRPose.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A3A05802B04971B00017309 /* PlatformXRPose.h */; settings = {ATTRIBUTES = (Private, ); }; };
3A4C6A872BABF1C500597157 /* PublicSuffixStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A4C6A852BABF1C500597157 /* PublicSuffixStore.h */; settings = {ATTRIBUTES = (Private, ); }; };
3A7D62DA29D49EC900D57DAC /* SWRegistrationDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A7D62D829D49EC800D57DAC /* SWRegistrationDatabase.h */; settings = {ATTRIBUTES = (Private, ); }; };
3ABD156A297A289300AF9D76 /* GraphicsContextGLEnums.h in Headers */ = {isa = PBXBuildFile; fileRef = 3ABD1569297A289200AF9D76 /* GraphicsContextGLEnums.h */; settings = {ATTRIBUTES = (Private, ); }; };
3ABD156C297A340100AF9D76 /* GraphicsContextGLActiveInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 3ABD156B297A340000AF9D76 /* GraphicsContextGLActiveInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
Expand Down Expand Up @@ -6651,8 +6651,6 @@
00146288103CD1DE000B20DB /* OriginAccessEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OriginAccessEntry.cpp; sourceTree = "<group>"; };
00146289103CD1DE000B20DB /* OriginAccessEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OriginAccessEntry.h; sourceTree = "<group>"; };
003F1FE911E6AB43008258D9 /* UserContentTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserContentTypes.h; sourceTree = "<group>"; };
0081FEFD16B0A244008AAA7A /* PublicSuffix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PublicSuffix.h; sourceTree = "<group>"; };
0081FEFE16B0A2B6008AAA7A /* PublicSuffixCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PublicSuffixCocoa.mm; sourceTree = "<group>"; };
00B9318113BA867F0035A948 /* XMLDocumentParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XMLDocumentParser.cpp; sourceTree = "<group>"; };
00B9318213BA867F0035A948 /* XMLDocumentParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMLDocumentParser.h; sourceTree = "<group>"; };
00B9318313BA867F0035A948 /* XMLDocumentParserLibxml2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XMLDocumentParserLibxml2.cpp; sourceTree = "<group>"; };
Expand Down Expand Up @@ -9681,6 +9679,9 @@
3A2FE8CE2978CC7800BA1D92 /* GCGLSpan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCGLSpan.h; sourceTree = "<group>"; };
3A3A057F2B04971B00017309 /* PlatformXRPose.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformXRPose.cpp; sourceTree = "<group>"; };
3A3A05802B04971B00017309 /* PlatformXRPose.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformXRPose.h; sourceTree = "<group>"; };
3A4C6A842BABF1C500597157 /* PublicSuffixStore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PublicSuffixStore.cpp; sourceTree = "<group>"; };
3A4C6A852BABF1C500597157 /* PublicSuffixStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PublicSuffixStore.h; sourceTree = "<group>"; };
3A4C6A882BABF3CF00597157 /* PublicSuffixStoreCocoa.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PublicSuffixStoreCocoa.mm; sourceTree = "<group>"; };
3A7D62D729D49EC800D57DAC /* SWRegistrationDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SWRegistrationDatabase.cpp; sourceTree = "<group>"; };
3A7D62D829D49EC800D57DAC /* SWRegistrationDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWRegistrationDatabase.h; sourceTree = "<group>"; };
3ABD1569297A289200AF9D76 /* GraphicsContextGLEnums.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GraphicsContextGLEnums.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -30592,7 +30593,7 @@
CDA29A0C1CBD9CFE00901CCF /* PlaybackSessionModelMediaElement.mm */,
CDC7470024BE267900C1868B /* PowerSourceNotifier.h */,
CDC7470124BE267900C1868B /* PowerSourceNotifier.mm */,
0081FEFE16B0A2B6008AAA7A /* PublicSuffixCocoa.mm */,
3A4C6A882BABF3CF00597157 /* PublicSuffixStoreCocoa.mm */,
5117F30C25E6101F002A9F1E /* RemoteCommandListenerCocoa.h */,
5117F30A25E6101E002A9F1E /* RemoteCommandListenerCocoa.mm */,
465A8E781C8A24CE00E7D3E4 /* RuntimeApplicationChecksCocoa.mm */,
Expand Down Expand Up @@ -34016,7 +34017,8 @@
7BDDA349275A01300038659E /* ProcessIdentity.h */,
1CC54AFB270F92DA005BF8BE /* ProcessQualified.h */,
F47A633C1FF6FD500081B3CC /* PromisedAttachmentInfo.h */,
0081FEFD16B0A244008AAA7A /* PublicSuffix.h */,
3A4C6A842BABF1C500597157 /* PublicSuffixStore.cpp */,
3A4C6A852BABF1C500597157 /* PublicSuffixStore.h */,
5C97A3361F5F7A6500105207 /* RectEdges.h */,
CA1635DC2072E76900E7D2CE /* ReferrerPolicy.cpp */,
9831AE49154225A200FE2644 /* ReferrerPolicy.h */,
Expand Down Expand Up @@ -41490,7 +41492,7 @@
57303BEF200980C600355965 /* PublicKeyCredentialDescriptor.h in Headers */,
57303C0A20099BAD00355965 /* PublicKeyCredentialRequestOptions.h in Headers */,
57303BEB20097F4000355965 /* PublicKeyCredentialType.h in Headers */,
0081FF0016B0A2D3008AAA7A /* PublicSuffix.h in Headers */,
3A4C6A872BABF1C500597157 /* PublicSuffixStore.h in Headers */,
10FB084B14E15C7E00A3DB98 /* PublicURLManager.h in Headers */,
EBA75C46275EC61A00D6D31C /* PushCrypto.h in Headers */,
EB9AD8CB27646E9400D893A4 /* PushDatabase.h in Headers */,
Expand Down
7 changes: 4 additions & 3 deletions Source/WebCore/dom/Document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@
#include "Position.h"
#include "ProcessingInstruction.h"
#include "PseudoClassChangeInvalidation.h"
#include "PublicSuffix.h"
#include "PublicSuffixStore.h"
#include "Quirks.h"
#include "RTCNetworkManager.h"
#include "Range.h"
Expand Down Expand Up @@ -4065,8 +4065,9 @@ const URL& Document::urlForBindings() const
return false;

auto areSameSiteIgnoringPublicSuffix = [](StringView domain, StringView otherDomain) {
auto domainString = topPrivatelyControlledDomain(domain.toStringWithoutCopying());
auto otherDomainString = topPrivatelyControlledDomain(otherDomain.toStringWithoutCopying());
auto& publicSuffixStore = PublicSuffixStore::singleton();
auto domainString = publicSuffixStore.topPrivatelyControlledDomain(domain.toStringWithoutCopying());
auto otherDomainString = publicSuffixStore.topPrivatelyControlledDomain(otherDomain.toStringWithoutCopying());
auto substringToSeparator = [](const String& string) -> String {
auto indexOfFirstSeparator = string.find('.');
if (indexOfFirstSeparator == notFound)
Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/loader/ResourceLoadStatistics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#include "ResourceLoadStatistics.h"

#include "KeyedCoding.h"
#include "PublicSuffix.h"
#include "PublicSuffixStore.h"
#include <wtf/MainThread.h>
#include <wtf/text/ASCIILiteral.h>
#include <wtf/text/StringBuilder.h>
Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/loader/cache/MemoryCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
#include "Image.h"
#include "LocalFrameView.h"
#include "Logging.h"
#include "PublicSuffix.h"
#include "PublicSuffixStore.h"
#include "SharedBuffer.h"
#include "WorkerGlobalScope.h"
#include "WorkerLoaderProxy.h"
Expand Down
8 changes: 4 additions & 4 deletions Source/WebCore/page/Quirks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ static HashMap<RegistrableDomain, String>& updatableStorageAccessUserAgentString
static inline bool isYahooMail(Document& document)
{
auto host = document.topDocument().url().host();
return host.startsWith("mail."_s) && topPrivatelyControlledDomain(host.toString()).startsWith("yahoo."_s);
return host.startsWith("mail."_s) && PublicSuffixStore::singleton().topPrivatelyControlledDomain(host.toString()).startsWith("yahoo."_s);
}
#endif

Expand Down Expand Up @@ -263,7 +263,7 @@ bool Quirks::shouldHideSearchFieldResultsButton() const
if (!needsQuirks())
return false;

if (topPrivatelyControlledDomain(m_document->topDocument().url().host().toString()).startsWith("google."_s))
if (PublicSuffixStore::singleton().topPrivatelyControlledDomain(m_document->topDocument().url().host().toString()).startsWith("google."_s))
return true;
#endif
return false;
Expand Down Expand Up @@ -454,13 +454,13 @@ bool Quirks::shouldDisableWritingSuggestionsByDefaultQuirk() const
#if ENABLE(TOUCH_EVENTS)
bool Quirks::isAmazon() const
{
return topPrivatelyControlledDomain(m_document->topDocument().url().host().toString()).startsWith("amazon."_s);
return PublicSuffixStore::singleton().topPrivatelyControlledDomain(m_document->topDocument().url().host().toString()).startsWith("amazon."_s);
}

bool Quirks::isGoogleMaps() const
{
auto& url = m_document->topDocument().url();
return topPrivatelyControlledDomain(url.host().toString()).startsWith("google."_s) && startsWithLettersIgnoringASCIICase(url.path(), "/maps/"_s);
return PublicSuffixStore::singleton().topPrivatelyControlledDomain(url.host().toString()).startsWith("google."_s) && startsWithLettersIgnoringASCIICase(url.path(), "/maps/"_s);
}

// rdar://49124313
Expand Down
8 changes: 4 additions & 4 deletions Source/WebCore/page/SecurityOrigin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
#include "BlobURL.h"
#include "LegacySchemeRegistry.h"
#include "OriginAccessEntry.h"
#include "PublicSuffix.h"
#include "PublicSuffixStore.h"
#include "RuntimeApplicationChecks.h"
#include "SecurityPolicy.h"
#include <pal/text/TextEncoding.h>
Expand Down Expand Up @@ -423,11 +423,11 @@ bool SecurityOrigin::isSameSiteAs(const SecurityOrigin& other) const
if (isOpaque())
return isSameOriginAs(other);

auto topDomain = topPrivatelyControlledDomain(domain());
auto topDomain = PublicSuffixStore::singleton().topPrivatelyControlledDomain(domain());
if (topDomain.isEmpty())
return host() == other.host();

return topDomain == topPrivatelyControlledDomain(other.domain());
return topDomain == PublicSuffixStore::singleton().topPrivatelyControlledDomain(other.domain());
}

bool SecurityOrigin::isMatchingRegistrableDomainSuffix(const String& domainSuffix, bool treatIPAddressAsDomain) const
Expand All @@ -444,7 +444,7 @@ bool SecurityOrigin::isMatchingRegistrableDomainSuffix(const String& domainSuffi
if (domainSuffix.length() == host().length())
return true;

return !isPublicSuffix(domainSuffix);
return !PublicSuffixStore::singleton().isPublicSuffix(domainSuffix);
}

bool SecurityOrigin::isPotentiallyTrustworthy() const
Expand Down
4 changes: 2 additions & 2 deletions Source/WebCore/page/csp/ContentSecurityPolicySourceList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
#include "ContentSecurityPolicy.h"
#include "ContentSecurityPolicyDirectiveNames.h"
#include "ParsingUtilities.h"
#include "PublicSuffix.h"
#include "PublicSuffixStore.h"
#include <pal/text/TextEncoding.h>
#include <wtf/ASCIICType.h>
#include <wtf/NeverDestroyed.h>
Expand Down Expand Up @@ -212,7 +212,7 @@ bool ContentSecurityPolicySourceList::isValidSourceForExtensionMode(const Conten
if (!isRestrictedDirectiveForMode(m_directiveName, ContentSecurityPolicyModeForExtension::ManifestV2))
return true;

if (parsedSource.host.hasWildcard && isPublicSuffix(parsedSource.host.value))
if (parsedSource.host.hasWildcard && PublicSuffixStore::singleton().isPublicSuffix(parsedSource.host.value))
return false;

if (equalLettersIgnoringASCIICase(parsedSource.scheme, "blob"_s))
Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/platform/Curl.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ list(APPEND WebCore_SOURCES
platform/network/curl/NetworkStorageSessionCurl.cpp
platform/network/curl/OpenSSLHelper.cpp
platform/network/curl/ProtectionSpaceCurl.cpp
platform/network/curl/PublicSuffixCurl.cpp
platform/network/curl/PublicSuffixStoreCurl.cpp
platform/network/curl/ResourceErrorCurl.cpp
platform/network/curl/ResourceRequestCurl.cpp
platform/network/curl/ResourceResponseCurl.cpp
Expand Down
101 changes: 101 additions & 0 deletions Source/WebCore/platform/PublicSuffixStore.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Copyright (C) 2024 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "config.h"
#include "PublicSuffixStore.h"

#include <wtf/CrossThreadCopier.h>
#include <wtf/NeverDestroyed.h>

namespace WebCore {

PublicSuffixStore& PublicSuffixStore::singleton()
{
static LazyNeverDestroyed<PublicSuffixStore> store;
static std::once_flag flag;
std::call_once(flag, [&] {
store.construct();
});
return store.get();
}

void PublicSuffixStore::clearHostTopPrivatelyControlledDomainCache()
{
Locker locker { m_HostTopPrivatelyControlledDomainCacheLock };
m_hostTopPrivatelyControlledDomainCache.clear();
}

bool PublicSuffixStore::isPublicSuffix(StringView domain) const
{
return platformIsPublicSuffix(domain);
}

String PublicSuffixStore::publicSuffix(const String& host) const
{
// FIXME: if host is a URL, we could drop these checks.
if (host.isEmpty() || !host.containsOnlyASCII())
return { };

const auto lowercaseHost = host.convertToASCIILowercase();
if (URL::hostIsIPAddress(lowercaseHost))
return { };

size_t separatorPosition;
for (unsigned labelStart = 0; (separatorPosition = host.find('.', labelStart)) != notFound; labelStart = separatorPosition + 1) {
auto candidate = lowercaseHost.substring(separatorPosition + 1);
if (isPublicSuffix(candidate))
return candidate;
}

return { };
}

String PublicSuffixStore::topPrivatelyControlledDomain(const String& host) const
{
// FIXME: if host is a URL, we could drop these checks.
if (host.isEmpty())
return { };

if (!host.containsOnlyASCII())
return host;

Locker locker { m_HostTopPrivatelyControlledDomainCacheLock };
auto hostCopy = crossThreadCopy(host);
auto& result = m_hostTopPrivatelyControlledDomainCache.ensure(hostCopy, [&] {
const auto lowercaseHost = hostCopy.convertToASCIILowercase();
if (lowercaseHost == "localhost"_s || URL::hostIsIPAddress(lowercaseHost))
return lowercaseHost;

return platformTopPrivatelyControlledDomain(lowercaseHost);
}).iterator->value;

constexpr auto maxHostTopPrivatelyControlledDomainCache = 128;
if (m_hostTopPrivatelyControlledDomainCache.size() > maxHostTopPrivatelyControlledDomainCache)
m_hostTopPrivatelyControlledDomainCache.remove(m_hostTopPrivatelyControlledDomainCache.random());

This comment has been minimized.

Copy link
@cdumez

cdumez Apr 8, 2024

Contributor

This invalidates auto& result above I think, which is bad considering we're using result later on.


return result.isolatedCopy();
}

} // namespace WebCore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
* Copyright (C) 2024 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
Expand All @@ -25,13 +25,41 @@

#pragma once

#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
#include <wtf/text/StringHash.h>
#include <wtf/text/WTFString.h>

namespace WebCore {

WEBCORE_EXPORT bool isPublicSuffix(StringView domain);
WEBCORE_EXPORT String topPrivatelyControlledDomain(const String& domain);
WEBCORE_EXPORT void setTopPrivatelyControlledDomain(const String& domain, const String& topPrivatelyControlledDomain);
String decodeHostName(const String& domain);
class PublicSuffixStore {
public:
WEBCORE_EXPORT static PublicSuffixStore& singleton();

// https://url.spec.whatwg.org/#host-public-suffix
WEBCORE_EXPORT bool isPublicSuffix(StringView domain) const;
WEBCORE_EXPORT String publicSuffix(const String& domain) const;
WEBCORE_EXPORT String topPrivatelyControlledDomain(const String& host) const;
WEBCORE_EXPORT void clearHostTopPrivatelyControlledDomainCache();

#if PLATFORM(COCOA)
WEBCORE_EXPORT void enablePublicSuffixCache();
WEBCORE_EXPORT void addPublicSuffix(const String& publicSuffix);
#endif

private:
friend LazyNeverDestroyed<PublicSuffixStore>;
PublicSuffixStore() = default;

bool platformIsPublicSuffix(StringView domain) const;
String platformTopPrivatelyControlledDomain(const String& host) const;

mutable Lock m_HostTopPrivatelyControlledDomainCacheLock;
mutable HashMap<String, String, ASCIICaseInsensitiveHash> m_hostTopPrivatelyControlledDomainCache WTF_GUARDED_BY_LOCK(m_HostTopPrivatelyControlledDomainCacheLock);
#if PLATFORM(COCOA)
mutable Lock m_publicSuffixCacheLock;
std::optional<HashSet<String, ASCIICaseInsensitiveHash>> m_publicSuffixCache WTF_GUARDED_BY_LOCK(m_publicSuffixCacheLock);
#endif
};

} // namespace WebCore
Loading

0 comments on commit ac05e4c

Please sign in to comment.