Skip to content

Commit 2bf1c74

Browse files
committed
WebContent logs during launch are not emitted
https://bugs.webkit.org/show_bug.cgi?id=291839 rdar://149683032 Reviewed by Chris Dumez. WebContent logs during launch are not emitted when logd is blocked in the sandbox because the log streaming channel to the UI process is not set up until WebProcess::platformInitializeWebProcess is called. This patch addresses this by sending logs emitted in this time interval over the XPC connection to the UI process and emit the logs there. Test: Tools/TestWebKitAPI/Tests/WebKit/LogForwarding.mm * Source/JavaScriptCore/API/JSValue.mm: (createStructHandlerMap): * Source/JavaScriptCore/API/JSWrapperMap.mm: (parsePropertyAttributes): * Source/JavaScriptCore/API/ObjcRuntimeExtras.h: (adoptSystem): Deleted. * Source/WTF/wtf/SystemFree.h: (WTF::adoptSystem): * Source/WebKit/Shared/Cocoa/LaunchLogHook.h: Added. * Source/WebKit/Shared/Cocoa/LaunchLogHook.mm: Added. (WebKit::LaunchLogHook::singleton): (WebKit::LaunchLogHook::initialize): (WebKit::LaunchLogHook::disable): * Source/WebKit/Shared/Cocoa/LaunchLogMessages.h: Added. * Source/WebKit/Shared/EntryPointUtilities/Cocoa/XPCService/XPCServiceMain.mm: (WebKit::initializeLogd): (WebKit::XPCServiceEventHandler): * Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h: * Source/WebKit/UIProcess/API/Cocoa/WKWebViewTesting.mm: (-[WKWebView _launchLogsCountForTesting]): * Source/WebKit/UIProcess/Cocoa/WebProcessProxyCocoa.mm: (WebKit::WebProcessProxy::xpcEventHandler const): (WebKit::WebProcessProxy::XPCEventHandler::handleXPCEvent const): (WebKit::WebProcessProxy::XPCEventHandler::XPCEventHandler): * Source/WebKit/UIProcess/Launcher/cocoa/ProcessLauncherCocoa.mm: * Source/WebKit/UIProcess/WebProcessProxy.h: * Source/WebKit/WebKit.xcodeproj/project.pbxproj: * Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm: (WebKit::registerLogClient): * Tools/TestWebKitAPI/Tests/WebKit/LogForwarding.mm: (TEST(WebKit, LaunchLogs)): Canonical link: https://commits.webkit.org/300971@main
1 parent 5820dfd commit 2bf1c74

19 files changed

Lines changed: 317 additions & 18 deletions

File tree

‎Source/JavaScriptCore/API/JSValue.mm‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1275,7 +1275,7 @@ - (JSValue *)initWithValue:(JSValueRef)value inContext:(JSContext *)context
12751275
char idType[3];
12761276
// Check 2nd argument type is "@"
12771277
{
1278-
auto secondType = adoptSystem<char[]>(method_copyArgumentType(method, 3));
1278+
auto secondType = WTF::adoptSystem<char[]>(method_copyArgumentType(method, 3));
12791279
if (strcmp(secondType.get(), "@") != 0)
12801280
return;
12811281
}
@@ -1284,7 +1284,7 @@ - (JSValue *)initWithValue:(JSValueRef)value inContext:(JSContext *)context
12841284
if (strcmp(idType, "@") != 0)
12851285
return;
12861286
{
1287-
auto type = adoptSystem<char[]>(method_copyArgumentType(method, 2));
1287+
auto type = WTF::adoptSystem<char[]>(method_copyArgumentType(method, 2));
12881288
structHandlers->add(StringImpl::createFromCString(type.get()), (StructTagHandler) { selector, 0 });
12891289
}
12901290
});
@@ -1300,7 +1300,7 @@ - (JSValue *)initWithValue:(JSValueRef)value inContext:(JSContext *)context
13001300
if (method_getNumberOfArguments(method) != 2)
13011301
return;
13021302
// Try to find a matching valueWith<Foo>:context: method.
1303-
auto type = adoptSystem<char[]>(method_copyReturnType(method));
1303+
auto type = WTF::adoptSystem<char[]>(method_copyReturnType(method));
13041304
StructHandlers::iterator iter = structHandlers->find(String::fromLatin1(type.get()));
13051305
if (iter == structHandlers->end())
13061306
return;

‎Source/JavaScriptCore/API/JSWrapperMap.mm‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ static bool parsePropertyAttributes(objc_property_t objcProperty, Property& prop
296296
{
297297
bool readonly = false;
298298
unsigned attributeCount;
299-
auto attributes = adoptSystem<objc_property_attribute_t[]>(property_copyAttributeList(objcProperty, &attributeCount));
299+
auto attributes = WTF::adoptSystem<objc_property_attribute_t[]>(property_copyAttributeList(objcProperty, &attributeCount));
300300
if (attributeCount) {
301301
for (unsigned i = 0; i < attributeCount; ++i) {
302302
switch (*(attributes[i].name)) {

‎Source/JavaScriptCore/API/ObjcRuntimeExtras.h‎

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,6 @@
3434

3535
WTF_ALLOW_UNSAFE_BUFFER_USAGE_BEGIN
3636

37-
template<typename T, typename U>
38-
inline std::unique_ptr<T, WTF::SystemFree<T>> adoptSystem(U value)
39-
{
40-
return std::unique_ptr<T, WTF::SystemFree<T>>(value);
41-
}
42-
4337
inline bool protocolImplementsProtocol(Protocol *candidate, Protocol *target)
4438
{
4539
auto protocolProtocols = protocol_copyProtocolListSpan(candidate);

‎Source/WTF/wtf/SystemFree.h‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,10 @@ struct SystemFree<T[]> {
4949
}
5050
};
5151

52+
template<typename T, typename U>
53+
inline std::unique_ptr<T, WTF::SystemFree<T>> adoptSystem(U value)
54+
{
55+
return std::unique_ptr<T, WTF::SystemFree<T>>(value);
56+
}
57+
5258
} // namespace WTF
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright (C) 2025 Apple Inc. All rights reserved.
3+
*
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that the following conditions
6+
* are met:
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.
12+
*
13+
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15+
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17+
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23+
* THE POSSIBILITY OF SUCH DAMAGE.
24+
*/
25+
26+
#pragma once
27+
28+
#if ENABLE(LOGD_BLOCKING_IN_WEBCONTENT)
29+
30+
#import <wtf/NeverDestroyed.h>
31+
#import <wtf/OSObjectPtr.h>
32+
#import <wtf/spi/darwin/XPCSPI.h>
33+
34+
namespace WebKit {
35+
36+
class LaunchLogHook {
37+
friend class LazyNeverDestroyed<LaunchLogHook>;
38+
public:
39+
static LaunchLogHook& singleton();
40+
41+
void initialize(xpc_connection_t);
42+
void disable();
43+
44+
private:
45+
LaunchLogHook() = default;
46+
47+
OSObjectPtr<xpc_connection_t> m_connection;
48+
};
49+
50+
} // namespace WebKit
51+
52+
#endif // ENABLE(LOGD_BLOCKING_IN_WEBCONTENT)
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright (C) 2025 Apple Inc. All rights reserved.
3+
*
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that the following conditions
6+
* are met:
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.
12+
*
13+
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15+
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17+
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23+
* THE POSSIBILITY OF SUCH DAMAGE.
24+
*/
25+
26+
#import "config.h"
27+
#import "LaunchLogHook.h"
28+
29+
#import "LaunchLogMessages.h"
30+
#import "Logging.h"
31+
#import "XPCEndpoint.h"
32+
#import <wtf/BlockPtr.h>
33+
#import <wtf/SystemFree.h>
34+
#import <wtf/spi/cocoa/OSLogSPI.h>
35+
36+
#if ENABLE(LOGD_BLOCKING_IN_WEBCONTENT)
37+
38+
namespace WebKit {
39+
40+
LaunchLogHook& LaunchLogHook::singleton()
41+
{
42+
static std::once_flag onceKey;
43+
static LazyNeverDestroyed<LaunchLogHook> logHook;
44+
std::call_once(onceKey, [] {
45+
logHook.construct();
46+
});
47+
return logHook.get();
48+
}
49+
50+
void LaunchLogHook::initialize(xpc_connection_t connection)
51+
{
52+
m_connection = connection;
53+
54+
static os_log_hook_t prevHook = nullptr;
55+
56+
auto blockPtr = makeBlockPtr([](os_log_type_t type, os_log_message_t msg) {
57+
if (prevHook)
58+
prevHook(type, msg);
59+
60+
if (!LaunchLogHook::singleton().m_connection)
61+
return;
62+
63+
if (type & OS_LOG_TYPE_DEBUG)
64+
return;
65+
66+
if (type == OS_LOG_TYPE_FAULT)
67+
type = OS_LOG_TYPE_ERROR;
68+
69+
if (auto messageString = WTF::adoptSystem<char[]>(os_log_copy_message_string(msg))) {
70+
auto message = adoptOSObject(xpc_dictionary_create(nullptr, nullptr, 0));
71+
xpc_dictionary_set_string(message.get(), XPCEndpoint::xpcMessageNameKey, logMessageName);
72+
if (auto* subsystem = msg->subsystem)
73+
xpc_dictionary_set_string(message.get(), subsystemKey, subsystem);
74+
if (auto* category = msg->category)
75+
xpc_dictionary_set_string(message.get(), categoryKey, category);
76+
xpc_dictionary_set_string(message.get(), messageStringKey, messageString.get());
77+
xpc_dictionary_set_uint64(message.get(), logTypeKey, type);
78+
xpc_connection_send_message(LaunchLogHook::singleton().m_connection.get(), message.get());
79+
}
80+
});
81+
82+
prevHook = os_log_set_hook(OS_LOG_TYPE_DEFAULT, blockPtr.get());
83+
RELEASE_LOG(Process, "Installed launch log hook");
84+
}
85+
86+
void LaunchLogHook::disable()
87+
{
88+
RELEASE_LOG(Process, "Disabling launch log hook");
89+
auto message = adoptOSObject(xpc_dictionary_create(nullptr, nullptr, 0));
90+
xpc_dictionary_set_string(message.get(), XPCEndpoint::xpcMessageNameKey, disableLogMessageName);
91+
xpc_connection_send_message(m_connection.get(), message.get());
92+
m_connection = nullptr;
93+
}
94+
95+
} // namespace WebKit
96+
97+
#endif
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright (C) 2025 Apple Inc. All rights reserved.
3+
*
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that the following conditions
6+
* are met:
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.
12+
*
13+
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15+
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17+
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23+
* THE POSSIBILITY OF SUCH DAMAGE.
24+
*/
25+
26+
#pragma once
27+
28+
#if ENABLE(LOGD_BLOCKING_IN_WEBCONTENT)
29+
30+
#include <wtf/text/ASCIILiteral.h>
31+
32+
namespace WebKit {
33+
34+
constexpr auto logMessageName = "log-message"_s;
35+
constexpr auto subsystemKey = "subsystem"_s;
36+
constexpr auto categoryKey = "category"_s;
37+
constexpr auto messageStringKey = "message-string"_s;
38+
constexpr auto logTypeKey = "log-type"_s;
39+
constexpr auto disableLogMessageName = "disable-log-message"_s;
40+
41+
}
42+
43+
#endif // ENABLE(LOGD_BLOCKING_IN_WEBCONTENT)

‎Source/WebKit/Shared/EntryPointUtilities/Cocoa/XPCService/XPCServiceMain.mm‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
#import "config.h"
2727

28+
#import "LaunchLogHook.h"
2829
#import "Logging.h"
2930
#import "WKCrashReporter.h"
3031
#import "WebKitServiceNames.h"
@@ -85,11 +86,12 @@ static void initializeCFPrefs()
8586
#endif // ENABLE(CFPREFS_DIRECT_MODE)
8687
}
8788

88-
static void initializeLogd(bool disableLogging)
89+
static void initializeLogd(bool disableLogging, xpc_connection_t connection)
8990
{
9091
#if ENABLE(LOGD_BLOCKING_IN_WEBCONTENT)
9192
if (disableLogging) {
9293
os_trace_set_mode(OS_TRACE_MODE_OFF);
94+
LaunchLogHook::singleton().initialize(connection);
9395
return;
9496
}
9597
#else
@@ -177,7 +179,7 @@ void XPCServiceEventHandler(xpc_connection_t peer)
177179
WTF::initialize();
178180

179181
bool disableLogging = xpc_dictionary_get_bool(event, "disable-logging");
180-
initializeLogd(disableLogging);
182+
initializeLogd(disableLogging, retainedPeerConnection.get());
181183

182184
if (RetainPtr languages = xpc_dictionary_get_value(event, "OverrideLanguages")) {
183185
Vector<String> newLanguages;

‎Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ struct WKAppPrivacyReportTestingData {
173173
- (void)_cancelFixedColorExtensionFadeAnimationsForTesting;
174174

175175
- (unsigned)_forwardedLogsCountForTesting;
176+
- (bool)_receivedLogsDuringLaunchForTesting;
176177

177178
- (void)_modelProcessModelPlayerCountForTesting:(void(^)(NSUInteger))completionHandler;
178179

‎Source/WebKit/UIProcess/API/Cocoa/WKWebViewTesting.mm‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,15 @@ - (unsigned)_forwardedLogsCountForTesting
10801080
#endif
10811081
}
10821082

1083+
- (bool)_receivedLogsDuringLaunchForTesting
1084+
{
1085+
#if ENABLE(LOGD_BLOCKING_IN_WEBCONTENT)
1086+
if (RefPtr mainFrame = _page->mainFrame())
1087+
return mainFrame->process().receivedLogsDuringLaunchForTesting();
1088+
#endif
1089+
return 0;
1090+
}
1091+
10831092
- (void)_modelProcessModelPlayerCountForTesting:(void(^)(NSUInteger))completionHandler
10841093
{
10851094
#if ENABLE(MODEL_PROCESS)

0 commit comments

Comments
 (0)