Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 4ed5ff4bf1eeaa3c1c76abc87644016fe7a61203
      
https://github.com/WebKit/WebKit/commit/4ed5ff4bf1eeaa3c1c76abc87644016fe7a61203
  Author: Ben Nham <[email protected]>
  Date:   2026-03-23 (Mon, 23 Mar 2026)

  Changed paths:
    M Source/WebCore/page/UserScript.cpp
    M Source/WebCore/page/UserScript.h
    M Source/WebCore/page/UserStyleSheet.cpp
    M Source/WebCore/page/UserStyleSheet.h
    M Source/WebKit/Platform/IPC/TransferString.cpp
    M Source/WebKit/Platform/IPC/TransferString.h
    M Source/WebKit/Platform/IPC/cocoa/TransferStringCocoa.mm
    M Source/WebKit/Scripts/webkit/messages.py
    M Source/WebKit/Shared/WebUserContentControllerDataTypes.h
    M Source/WebKit/Shared/WebUserContentControllerDataTypes.serialization.in
    M Source/WebKit/UIProcess/Extensions/Cocoa/WebExtensionCocoa.mm
    M Source/WebKit/UIProcess/Extensions/WebExtension.cpp
    M Source/WebKit/UIProcess/Extensions/WebExtension.h
    M Source/WebKit/UIProcess/Extensions/glib/WebExtensionGLib.cpp
    M Source/WebKit/UIProcess/UserContent/WebUserContentControllerProxy.cpp
    M Source/WebKit/UIProcess/UserContent/WebUserContentControllerProxy.h
    M Source/WebKit/WebProcess/UserContent/WebUserContentController.cpp
    M Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebExtensionAPIScripting.mm

  Log Message:
  -----------
  Reduce memory overhead of user scripts and user styles in extensions with 
many distinct match patterns
https://bugs.webkit.org/show_bug.cgi?id=310393
rdar://169436824

Reviewed by Timothy Hatcher.

Extensions can specify user scripts and user styles with many distinct match 
patterns, either
directly via the extension manifest or due to user behavior (e.g. if the user 
decides to load
extensions only selectively on certain origins, and that origin list is very 
long).

In the current implementation of web extensions, this can lead to memory 
explosion because each
distinct match pattern carries its own copy of the same exact user script and 
user style strings
(see how `WebExtensionContext::addInjectedContent` loops over each pattern and 
creates an
`API::UserScript` object for each pattern). We have seen users that eventually 
accumulate match
lists of 300+ origins, which leads to 300+ copies of user scripts and user 
styles and which can
cause WebContent to OOM.

This patch fixes the issue by addressing three places where we are 
unnecessarily duplicating strings:

1. In `WebExtension`, we keep a cached copy of data and string resources. 
However, if a data
resource is already cached for a path, then we always create a new string 
instance from that cached
data resource. So 100 calls to `WebExtension::resourceStringForPath` can lead 
to 100 String
instances backed by 100 distinct StringImpls even if CacheResult::Yes is used. 
To fix this, we
separate the cached data and cached string hash maps in WebExtension so that 
cached strings are
always associated with a single String instance.

2. `WebUserContentControllerProxy` in UIProcess IPCs user script and user style 
strings to
`WebUserContentController` in WebProcess. The same strings are sent to all 
processes in the process
pool, but in the current implementation each process will have its own private 
copy of the
string. To fix this, use `IPC::TransferString` to transfer the string across 
processes, which allows
the strings in UIProcess and all WebProcesses to be backed by the same single 
memory allocation (see
SharedSpan8 and SharedSpan16 in TransferString).

3. Within the same WebContent process, there can be duplicate user script or 
user style strings,
because each distinct match pattern is associated with a separate UserScript 
object with a differing
match pattern but the same source string. To fix this, we now intern source 
strings in both
UserScript and UserStyleSheet.

Test: Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebExtensionAPIScripting.mm

* Source/WebCore/page/UserScript.cpp: Implement WebProcess user script string 
interning.
(WebCore::sourceStrings):
(WebCore::internedSourceString):
(WebCore::UserScript::UserScript):
(WebCore::UserScript::~UserScript):
* Source/WebCore/page/UserScript.h:

* Source/WebCore/page/UserStyleSheet.cpp: Implement WebProcess user style 
string interning.
(WebCore::styleStrings):
(WebCore::internedStyleString):
(WebCore::UserStyleSheet::UserStyleSheet):
(WebCore::UserStyleSheet::~UserStyleSheet):
* Source/WebCore/page/UserStyleSheet.h:

* Source/WebKit/Platform/IPC/TransferString.cpp: Make TransferString copyable. 
It was already copyable previously in a roundabout way using toIPCData.
(IPC::TransferString::TransferString):
(IPC::TransferString::operator=):
(IPC::TransferString::shouldCache const):
* Source/WebKit/Platform/IPC/TransferString.h:
* Source/WebKit/Platform/IPC/cocoa/TransferStringCocoa.mm:
(IPC::TransferString::createCached):

* Source/WebKit/Scripts/webkit/messages.py: Use TransferString to IPC user 
script and user style strings to WebProcess. This requires keeping a cache of 
TransferStrings in WebUserContentControllerProxy.
(headers_for_type):
* Source/WebKit/Shared/WebUserContentControllerDataTypes.h:
* Source/WebKit/Shared/WebUserContentControllerDataTypes.serialization.in:
* Source/WebKit/UIProcess/UserContent/WebUserContentControllerProxy.cpp:
(WebKit::WebUserContentControllerProxy::cachedTransferString const):
(WebKit::WebUserContentControllerProxy::resetTransferStringCache):
(WebKit::WebUserContentControllerProxy::dataFromUserScript const):
(WebKit::WebUserContentControllerProxy::dataFromUserStyleSheet const):
(WebKit::WebUserContentControllerProxy::parametersForProcess const):
(WebKit::WebUserContentControllerProxy::addUserScript):
(WebKit::WebUserContentControllerProxy::removeUserScript):
(WebKit::WebUserContentControllerProxy::removeAllUserScripts):
(WebKit::WebUserContentControllerProxy::addUserStyleSheet):
(WebKit::WebUserContentControllerProxy::removeUserStyleSheet):
(WebKit::WebUserContentControllerProxy::removeAllUserStyleSheets):
* Source/WebKit/UIProcess/UserContent/WebUserContentControllerProxy.h:
* Source/WebKit/WebProcess/UserContent/WebUserContentController.cpp:
(WebKit::userScriptFromData):
(WebKit::userStyleSheetFromData):
(WebKit::WebUserContentController::addUserScripts):
(WebKit::WebUserContentController::addUserStyleSheets):

* Source/WebKit/UIProcess/Extensions/WebExtension.cpp: Cache extension data and 
string resources separately, so that cached strings are always backed by the 
same string instance.
(WebKit::WebExtension::toDataResources):
(WebKit::WebExtension::toStringResources):
(WebKit::WebExtension::WebExtension):
(WebKit::WebExtension::resourceStringForPath):
(WebKit::WebExtension::supportedLocales):
* Source/WebKit/UIProcess/Extensions/Cocoa/WebExtensionCocoa.mm:
(WebKit::WebExtension::WebExtension):
(WebKit::WebExtension::resourceDataForPath):
* Source/WebKit/UIProcess/Extensions/WebExtension.h:
* Source/WebKit/UIProcess/Extensions/glib/WebExtensionGLib.cpp:
(WebKit::WebExtension::WebExtension):
(WebKit::WebExtension::resourceDataForPath):

* Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebExtensionAPIScripting.mm:
(TestWebKitAPI::TEST(WKWebExtensionAPIScripting, 
ContentScriptsAndStyleSheetsWithManyMatchPatterns)):

Canonical link: https://commits.webkit.org/309775@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications

Reply via email to