diff --git a/Ladybird/MachPortServer.cpp b/Ladybird/MachPortServer.cpp index 4a7868627b4..dfe8fb65c3b 100644 --- a/Ladybird/MachPortServer.cpp +++ b/Ladybird/MachPortServer.cpp @@ -6,7 +6,7 @@ #include "MachPortServer.h" #include -#include +#include namespace Ladybird { @@ -56,7 +56,7 @@ void MachPortServer::thread_loop() { while (!m_should_stop.load(MemoryOrder::memory_order_acquire)) { - WebView::ParentPortMessage message {}; + Core::Platform::ParentPortMessage message {}; // Get the pid of the child from the audit trailer so we can associate the port w/it mach_msg_options_t const options = MACH_RCV_MSG | MACH_RCV_TRAILER_TYPE(MACH_RCV_TRAILER_AUDIT) | MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT); @@ -68,7 +68,7 @@ void MachPortServer::thread_loop() break; } - if (message.header.msgh_id != WebView::SELF_TASK_PORT_MESSAGE_ID) { + if (message.header.msgh_id != Core::Platform::SELF_TASK_PORT_MESSAGE_ID) { dbgln("Received message with id {}, ignoring", message.header.msgh_id); continue; } diff --git a/Ladybird/WebContent/main.cpp b/Ladybird/WebContent/main.cpp index 417e36777f5..8e37c0f5527 100644 --- a/Ladybird/WebContent/main.cpp +++ b/Ladybird/WebContent/main.cpp @@ -46,7 +46,7 @@ #endif #if defined(AK_OS_MACOS) -# include +# include #endif static ErrorOr load_content_filters(); @@ -132,7 +132,7 @@ ErrorOr serenity_main(Main::Arguments arguments) #if defined(AK_OS_MACOS) if (!mach_server_name.is_empty()) { - WebView::register_with_mach_server(mach_server_name); + Core::Platform::register_with_mach_server(mach_server_name); } #endif diff --git a/Meta/gn/secondary/Userland/Libraries/LibCore/BUILD.gn b/Meta/gn/secondary/Userland/Libraries/LibCore/BUILD.gn index b5deeb9c711..7c0b6653740 100644 --- a/Meta/gn/secondary/Userland/Libraries/LibCore/BUILD.gn +++ b/Meta/gn/secondary/Userland/Libraries/LibCore/BUILD.gn @@ -72,6 +72,8 @@ source_set("sources") { "NetworkResponse.h", "Notifier.cpp", "Notifier.h", + "Platform/ProcessInfo.h", + "Platform/ProcessStatistics.h", "Process.cpp", "Process.h", "ProcessStatisticsReader.cpp", @@ -119,6 +121,19 @@ source_set("sources") { if (current_os == "mac") { sources += [ "MachPort.cpp" ] } + + if (current_os == "serenity") { + sources += [ "Platform/ProcessStatisticsSerenity.cpp" ] + } else if (current_os == "linux") { + sources += [ "Platform/ProcessStatisticsLinux.cpp" ] + } else if (current_os == "mac") { + sources += [ + "Platform/ProcessStatisticsMach.cpp", + "Platform/ProcessStatisticsMach.h", + ] + } else { + sources += [ "Platform/ProcessStatisticsUnimplemented.cpp" ] + } } source_set("filewatcher") { diff --git a/Meta/gn/secondary/Userland/Libraries/LibWebView/BUILD.gn b/Meta/gn/secondary/Userland/Libraries/LibWebView/BUILD.gn index eb5c19647f4..8438a5f3a6a 100644 --- a/Meta/gn/secondary/Userland/Libraries/LibWebView/BUILD.gn +++ b/Meta/gn/secondary/Userland/Libraries/LibWebView/BUILD.gn @@ -146,15 +146,6 @@ shared_library("LibWebView") { } if (current_os == "serenity") { - sources += [ - "OutOfProcessWebView.cpp", - "Platform/ProcessStatisticsSerenity.cpp", - ] - } else if (current_os == "linux") { - sources += [ "Platform/ProcessStatisticsLinux.cpp" ] - } else if (current_os == "mac") { - sources += [ "Platform/ProcessStatisticsMach.cpp" ] - } else { - sources += [ "Platform/ProcessStatisticsNoop.cpp" ] + sources += [ "OutOfProcessWebView.cpp" ] } } diff --git a/Userland/Libraries/LibCore/CMakeLists.txt b/Userland/Libraries/LibCore/CMakeLists.txt index 0c2a161ceb0..3ee499028a6 100644 --- a/Userland/Libraries/LibCore/CMakeLists.txt +++ b/Userland/Libraries/LibCore/CMakeLists.txt @@ -60,13 +60,25 @@ endif() # FIXME: Implement Core::FileWatcher for *BSD and Windows. if (SERENITYOS) - list(APPEND SOURCES FileWatcherSerenity.cpp) + list(APPEND SOURCES + FileWatcherSerenity.cpp + Platform/ProcessStatisticsSerenity.cpp + ) elseif (LINUX AND NOT EMSCRIPTEN) - list(APPEND SOURCES FileWatcherLinux.cpp) + list(APPEND SOURCES + FileWatcherLinux.cpp + Platform/ProcessStatisticsLinux.cpp + ) elseif (APPLE AND NOT IOS) - list(APPEND SOURCES FileWatcherMacOS.mm) + list(APPEND SOURCES + FileWatcherMacOS.mm + Platform/ProcessStatisticsMach.cpp + ) else() - list(APPEND SOURCES FileWatcherUnimplemented.cpp) + list(APPEND SOURCES + FileWatcherUnimplemented.cpp + Platform/ProcessStatisticsUnimplemented.cpp + ) endif() if (APPLE OR CMAKE_SYSTEM_NAME STREQUAL "GNU") diff --git a/Userland/Libraries/LibWebView/Platform/ProcessInfo.h b/Userland/Libraries/LibCore/Platform/ProcessInfo.h similarity index 53% rename from Userland/Libraries/LibWebView/Platform/ProcessInfo.h rename to Userland/Libraries/LibCore/Platform/ProcessInfo.h index 3a7dd6781a4..937b1f64c86 100644 --- a/Userland/Libraries/LibWebView/Platform/ProcessInfo.h +++ b/Userland/Libraries/LibCore/Platform/ProcessInfo.h @@ -12,39 +12,31 @@ # include #endif -namespace WebView { - -enum class ProcessType { - Chrome, - WebContent, - WebWorker, - SQLServer, - RequestServer, - ImageDecoder, -}; +namespace Core::Platform { struct ProcessInfo { - ProcessInfo(ProcessType type, pid_t pid) - : type(type) - , pid(pid) + explicit ProcessInfo(pid_t pid) + : pid(pid) { } - ProcessType type = ProcessType::WebContent; - pid_t pid; - u64 memory_usage_bytes = 0; - float cpu_percent = 0.0f; + virtual ~ProcessInfo() = default; - u64 time_spent_in_process = 0; + pid_t pid { 0 }; + + u64 memory_usage_bytes { 0 }; + float cpu_percent { 0.0f }; + + u64 time_spent_in_process { 0 }; #if defined(AK_OS_MACH) - Core::MachPort child_task_port; - ProcessInfo(pid_t pid, Core::MachPort&& port) : pid(pid) , child_task_port(move(port)) { } + + Core::MachPort child_task_port; #endif }; diff --git a/Userland/Libraries/LibCore/Platform/ProcessStatistics.h b/Userland/Libraries/LibCore/Platform/ProcessStatistics.h new file mode 100644 index 00000000000..f3b54846bf0 --- /dev/null +++ b/Userland/Libraries/LibCore/Platform/ProcessStatistics.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024, Andrew Kaster + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace Core::Platform { + +struct ProcessStatistics { + template + void for_each_process(Callback&& callback) + { + for (auto& process : processes) + callback(verify_cast(*process)); + } + + u64 total_time_scheduled { 0 }; + Vector> processes; +}; + +ErrorOr update_process_statistics(ProcessStatistics&); + +} diff --git a/Userland/Libraries/LibWebView/Platform/ProcessStatisticsLinux.cpp b/Userland/Libraries/LibCore/Platform/ProcessStatisticsLinux.cpp similarity index 86% rename from Userland/Libraries/LibWebView/Platform/ProcessStatisticsLinux.cpp rename to Userland/Libraries/LibCore/Platform/ProcessStatisticsLinux.cpp index 24a2e9de290..7f2f0131e31 100644 --- a/Userland/Libraries/LibWebView/Platform/ProcessStatisticsLinux.cpp +++ b/Userland/Libraries/LibCore/Platform/ProcessStatisticsLinux.cpp @@ -6,10 +6,10 @@ #include #include -#include +#include #include -namespace WebView { +namespace Core::Platform { static auto user_hz = sysconf(_SC_CLK_TCK); static auto page_size = sysconf(_SC_PAGESIZE); @@ -43,7 +43,7 @@ ErrorOr update_process_statistics(ProcessStatistics& statistics) statistics.total_time_scheduled = total_time_scheduled; for (auto& process : statistics.processes) { - auto proc_pid_stat_or_error = Core::File::open(MUST(String::formatted("/proc/{}/stat", process.pid)), Core::File::OpenMode::Read); + auto proc_pid_stat_or_error = Core::File::open(MUST(String::formatted("/proc/{}/stat", process->pid)), Core::File::OpenMode::Read); if (proc_pid_stat_or_error.is_error()) { // FIXME: Remove stale process from process list? continue; @@ -60,15 +60,15 @@ ErrorOr update_process_statistics(ProcessStatistics& statistics) if (res != 3) return Error::from_string_literal("Failed to parse /proc/pid/stat"); - process.memory_usage_bytes = rss * page_size; + process->memory_usage_bytes = rss * page_size; u64 const time_process = utime + stime; - float const time_scheduled_diff = time_process - process.time_spent_in_process; - process.time_spent_in_process = time_process; + float const time_scheduled_diff = time_process - process->time_spent_in_process; + process->time_spent_in_process = time_process; - process.cpu_percent = 0.0; + process->cpu_percent = 0.0; if (total_time_scheduled_diff > 0) { - process.cpu_percent = time_scheduled_diff / (total_time_scheduled_diff / ncpu_online) * 100.0f; + process->cpu_percent = time_scheduled_diff / (total_time_scheduled_diff / ncpu_online) * 100.0f; } } diff --git a/Userland/Libraries/LibWebView/Platform/ProcessStatisticsMach.cpp b/Userland/Libraries/LibCore/Platform/ProcessStatisticsMach.cpp similarity index 83% rename from Userland/Libraries/LibWebView/Platform/ProcessStatisticsMach.cpp rename to Userland/Libraries/LibCore/Platform/ProcessStatisticsMach.cpp index 9d5cc1096eb..a09d1acba59 100644 --- a/Userland/Libraries/LibWebView/Platform/ProcessStatisticsMach.cpp +++ b/Userland/Libraries/LibCore/Platform/ProcessStatisticsMach.cpp @@ -13,9 +13,9 @@ #include #include #include -#include +#include -namespace WebView { +namespace Core::Platform { static auto user_hz = sysconf(_SC_CLK_TCK); @@ -43,19 +43,19 @@ ErrorOr update_process_statistics(ProcessStatistics& statistics) for (auto& process : statistics.processes) { mach_task_basic_info_data_t basic_info {}; count = MACH_TASK_BASIC_INFO_COUNT; - res = task_info(process.child_task_port.port(), MACH_TASK_BASIC_INFO, reinterpret_cast(&basic_info), &count); + res = task_info(process->child_task_port.port(), MACH_TASK_BASIC_INFO, reinterpret_cast(&basic_info), &count); if (res != KERN_SUCCESS) { - dbgln("Failed to get task info for pid {}: {}", process.pid, mach_error_string(res)); + dbgln("Failed to get task info for pid {}: {}", process->pid, mach_error_string(res)); return Core::mach_error_to_error(res); } - process.memory_usage_bytes = basic_info.resident_size; + process->memory_usage_bytes = basic_info.resident_size; task_thread_times_info_data_t time_info {}; count = TASK_THREAD_TIMES_INFO_COUNT; - res = task_info(process.child_task_port.port(), TASK_THREAD_TIMES_INFO, reinterpret_cast(&time_info), &count); + res = task_info(process->child_task_port.port(), TASK_THREAD_TIMES_INFO, reinterpret_cast(&time_info), &count); if (res != KERN_SUCCESS) { - dbgln("Failed to get thread times info for pid {}: {}", process.pid, mach_error_string(res)); + dbgln("Failed to get thread times info for pid {}: {}", process->pid, mach_error_string(res)); return Core::mach_error_to_error(res); } @@ -64,12 +64,12 @@ ErrorOr update_process_statistics(ProcessStatistics& statistics) scratch_timeval = { static_cast(time_info.system_time.seconds), static_cast(time_info.system_time.microseconds) }; time_in_process += Duration::from_timeval(scratch_timeval); - auto time_diff_process = time_in_process - Duration::from_microseconds(process.time_spent_in_process); - process.time_spent_in_process = time_in_process.to_microseconds(); + auto time_diff_process = time_in_process - Duration::from_microseconds(process->time_spent_in_process); + process->time_spent_in_process = time_in_process.to_microseconds(); - process.cpu_percent = 0.0f; + process->cpu_percent = 0.0f; if (time_diff_process > Duration::zero()) - process.cpu_percent = 100.0f * static_cast(time_diff_process.to_microseconds()) / total_cpu_micro_diff; + process->cpu_percent = 100.0f * static_cast(time_diff_process.to_microseconds()) / total_cpu_micro_diff; } return {}; diff --git a/Userland/Libraries/LibWebView/Platform/ProcessStatisticsMach.h b/Userland/Libraries/LibCore/Platform/ProcessStatisticsMach.h similarity index 90% rename from Userland/Libraries/LibWebView/Platform/ProcessStatisticsMach.h rename to Userland/Libraries/LibCore/Platform/ProcessStatisticsMach.h index fd64d4ec755..c8ad3ea788e 100644 --- a/Userland/Libraries/LibWebView/Platform/ProcessStatisticsMach.h +++ b/Userland/Libraries/LibCore/Platform/ProcessStatisticsMach.h @@ -12,10 +12,10 @@ # error "This file is only available on Mach platforms" #endif -#include +#include #include -namespace WebView { +namespace Core::Platform { struct ChildPortMessage { mach_msg_header_t header; diff --git a/Userland/Libraries/LibWebView/Platform/ProcessStatisticsSerenity.cpp b/Userland/Libraries/LibCore/Platform/ProcessStatisticsSerenity.cpp similarity index 65% rename from Userland/Libraries/LibWebView/Platform/ProcessStatisticsSerenity.cpp rename to Userland/Libraries/LibCore/Platform/ProcessStatisticsSerenity.cpp index 0c3bc1fd8da..32f2a7fe956 100644 --- a/Userland/Libraries/LibWebView/Platform/ProcessStatisticsSerenity.cpp +++ b/Userland/Libraries/LibCore/Platform/ProcessStatisticsSerenity.cpp @@ -11,11 +11,10 @@ #endif #include +#include #include -#include -#include -namespace WebView { +namespace Core::Platform { ErrorOr update_process_statistics(ProcessStatistics& statistics) { @@ -28,25 +27,25 @@ ErrorOr update_process_statistics(ProcessStatistics& statistics) statistics.total_time_scheduled = total_time_scheduled; for (auto& process : statistics.processes) { - auto it = all_processes.processes.find_if([&](auto& entry) { return entry.pid == process.pid; }); + auto it = all_processes.processes.find_if([&](auto& entry) { return entry.pid == process->pid; }); if (!it.is_end()) { - process.memory_usage_bytes = it->amount_resident; + process->memory_usage_bytes = it->amount_resident; u64 time_process = 0; for (auto& thread : it->threads) { time_process += thread.time_user + thread.time_kernel; } - u64 time_scheduled_diff = time_process - process.time_spent_in_process; + u64 time_scheduled_diff = time_process - process->time_spent_in_process; - process.time_spent_in_process = time_process; - process.cpu_percent = 0.0; + process->time_spent_in_process = time_process; + process->cpu_percent = 0.0; if (total_time_scheduled_diff > 0) { - process.cpu_percent = static_cast((time_scheduled_diff * 1000) / total_time_scheduled_diff) / 10.0f; + process->cpu_percent = static_cast((time_scheduled_diff * 1000) / total_time_scheduled_diff) / 10.0f; } } else { - process.memory_usage_bytes = 0; - process.cpu_percent = 0.0; - process.time_spent_in_process = 0; + process->memory_usage_bytes = 0; + process->cpu_percent = 0.0; + process->time_spent_in_process = 0; } } diff --git a/Userland/Libraries/LibWebView/Platform/ProcessStatisticsNoop.cpp b/Userland/Libraries/LibCore/Platform/ProcessStatisticsUnimplemented.cpp similarity index 72% rename from Userland/Libraries/LibWebView/Platform/ProcessStatisticsNoop.cpp rename to Userland/Libraries/LibCore/Platform/ProcessStatisticsUnimplemented.cpp index d91eeb25b1f..46d7869d9cd 100644 --- a/Userland/Libraries/LibWebView/Platform/ProcessStatisticsNoop.cpp +++ b/Userland/Libraries/LibCore/Platform/ProcessStatisticsUnimplemented.cpp @@ -4,9 +4,9 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include -namespace WebView { +namespace Core::Platform { ErrorOr update_process_statistics(ProcessStatistics&) { diff --git a/Userland/Libraries/LibWebView/CMakeLists.txt b/Userland/Libraries/LibWebView/CMakeLists.txt index 1c0a1424fbf..8e1a7208b2b 100644 --- a/Userland/Libraries/LibWebView/CMakeLists.txt +++ b/Userland/Libraries/LibWebView/CMakeLists.txt @@ -21,22 +21,7 @@ set(SOURCES set(GENERATED_SOURCES ${CURRENT_LIB_GENERATED}) if (SERENITYOS) - list(APPEND SOURCES - OutOfProcessWebView.cpp - Platform/ProcessStatisticsSerenity.cpp - ) -elseif(LINUX AND NOT ANDROID) - list(APPEND SOURCES - Platform/ProcessStatisticsLinux.cpp - ) -elseif(APPLE) - list(APPEND SOURCES - Platform/ProcessStatisticsMach.cpp - ) -else() - list(APPEND SOURCES - Platform/ProcessStatisticsNoop.cpp - ) + list(APPEND SOURCES OutOfProcessWebView.cpp) endif() embed_as_string_view( diff --git a/Userland/Libraries/LibWebView/Platform/ProcessStatistics.h b/Userland/Libraries/LibWebView/Platform/ProcessStatistics.h deleted file mode 100644 index 8a9f6962619..00000000000 --- a/Userland/Libraries/LibWebView/Platform/ProcessStatistics.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2024, Andrew Kaster - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include - -namespace WebView { - -struct ProcessStatistics { - u64 total_time_scheduled = 0; - Vector processes; -}; - -ErrorOr update_process_statistics(ProcessStatistics&); - -} diff --git a/Userland/Libraries/LibWebView/ProcessInfo.h b/Userland/Libraries/LibWebView/ProcessInfo.h new file mode 100644 index 00000000000..5cf5c62479a --- /dev/null +++ b/Userland/Libraries/LibWebView/ProcessInfo.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024, Andrew Kaster + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +#if defined(AK_OS_MACH) +# include +#endif + +namespace WebView { + +enum class ProcessType { + Chrome, + WebContent, + WebWorker, + SQLServer, + RequestServer, + ImageDecoder, +}; + +struct ProcessInfo : public Core::Platform::ProcessInfo { + using Core::Platform::ProcessInfo::ProcessInfo; + + ProcessInfo(ProcessType type, pid_t pid) + : Core::Platform::ProcessInfo(pid) + , type(type) + { + } + + ProcessType type { ProcessType::WebContent }; +}; + +} diff --git a/Userland/Libraries/LibWebView/ProcessManager.cpp b/Userland/Libraries/LibWebView/ProcessManager.cpp index acbe4759fb6..960fd1e3fb7 100644 --- a/Userland/Libraries/LibWebView/ProcessManager.cpp +++ b/Userland/Libraries/LibWebView/ProcessManager.cpp @@ -88,15 +88,23 @@ void ProcessManager::initialize() #endif } +ProcessInfo* ProcessManager::find_process(pid_t pid) +{ + if (auto existing_process = m_statistics.processes.find_if([&](auto& info) { return info->pid == pid; }); !existing_process.is_end()) + return verify_cast(existing_process->ptr()); + + return nullptr; +} + void ProcessManager::add_process(ProcessType type, pid_t pid) { Threading::MutexLocker locker { m_lock }; dbgln("ProcessManager::add_process({}, {})", process_name_from_type(type), pid); - if (auto existing_process = m_statistics.processes.find_if([&](auto& info) { return info.pid == pid; }); !existing_process.is_end()) { + if (auto* existing_process = find_process(pid)) { existing_process->type = type; return; } - m_statistics.processes.append({ type, pid }); + m_statistics.processes.append(make(type, pid)); } #if defined(AK_OS_MACH) @@ -104,20 +112,21 @@ void ProcessManager::add_process(pid_t pid, Core::MachPort&& port) { Threading::MutexLocker locker { m_lock }; dbgln("ProcessManager::add_process({}, {:p})", pid, port.port()); - if (auto existing_process = m_statistics.processes.find_if([&](auto& info) { return info.pid == pid; }); !existing_process.is_end()) { + if (auto* existing_process = find_process(pid)) { existing_process->child_task_port = move(port); return; } - m_statistics.processes.append({ pid, move(port) }); + m_statistics.processes.append(make(pid, move(port))); } #endif void ProcessManager::remove_process(pid_t pid) { Threading::MutexLocker locker { m_lock }; - m_statistics.processes.remove_first_matching([&](auto& info) { - if (info.pid == pid) { - dbgln("ProcessManager: Remove process {} ({})", process_name_from_type(info.type), pid); + m_statistics.processes.remove_first_matching([&](auto const& info) { + if (info->pid == pid) { + auto type = verify_cast(*info).type; + dbgln("ProcessManager: Remove process {} ({})", process_name_from_type(type), pid); return true; } return false; @@ -146,7 +155,6 @@ String ProcessManager::generate_html() { Threading::MutexLocker locker { m_lock }; StringBuilder builder; - auto const& processes = m_statistics.processes; builder.append(R"( @@ -197,7 +205,7 @@ String ProcessManager::generate_html() )"sv); - for (auto const& process : processes) { + m_statistics.for_each_process([&](auto const& process) { builder.append(""sv); builder.append(""sv); builder.append(WebView::process_name_from_type(process.type)); @@ -212,7 +220,7 @@ String ProcessManager::generate_html() builder.append(MUST(String::formatted("{:.1f}", process.cpu_percent))); builder.append(""sv); builder.append(""sv); - } + }); builder.append(R"( diff --git a/Userland/Libraries/LibWebView/ProcessManager.h b/Userland/Libraries/LibWebView/ProcessManager.h index 8745a7a7fae..87a5ab1ab87 100644 --- a/Userland/Libraries/LibWebView/ProcessManager.h +++ b/Userland/Libraries/LibWebView/ProcessManager.h @@ -9,9 +9,10 @@ #include #include #include +#include #include #include -#include +#include namespace WebView { @@ -25,21 +26,20 @@ public: void add_process(WebView::ProcessType, pid_t); void remove_process(pid_t); + ProcessInfo* find_process(pid_t); #if defined(AK_OS_MACH) void add_process(pid_t, Core::MachPort&&); #endif void update_all_processes(); - Vector const& processes() const { return m_statistics.processes; } - String generate_html(); private: ProcessManager(); ~ProcessManager(); - ProcessStatistics m_statistics; + Core::Platform::ProcessStatistics m_statistics; Threading::Mutex m_lock; };