diff --git a/src/browser/client.cxx b/src/browser/client.cxx index fe15089..bbb9646 100644 --- a/src/browser/client.cxx +++ b/src/browser/client.cxx @@ -393,7 +393,7 @@ bool Browser::Client::IPCHandleMessage(int fd) { .resizeable = true, .frame = true, }; - plugin->windows.push_back(new Browser::PluginWindow(this, details, url, plugin, fd, header.window_id, header.plugin_id, false)); + plugin->windows.push_back(new Browser::PluginWindow(this, details, url, plugin, fd, &this->send_lock, header.window_id, header.plugin_id, false)); delete[] url; break; } @@ -406,7 +406,7 @@ bool Browser::Client::IPCHandleMessage(int fd) { CefRefPtr plugin = this->GetPluginFromFDAndID(client, header.plugin_id); if (plugin) { - CefRefPtr window = new Browser::WindowOSR(CefString((char*)url), header.w, header.h, fd, this, header.pid, header.window_id, header.plugin_id, plugin); + CefRefPtr window = new Browser::WindowOSR(CefString((char*)url), header.w, header.h, fd, this, &this->send_lock, header.pid, header.window_id, header.plugin_id, plugin); plugin->windows_osr.push_back(window); } delete[] url; @@ -516,12 +516,12 @@ void Browser::Client::StartPlugin(uint64_t client_id, std::string id, std::strin if (!g.deleted && g.uid == client_id) { for (auto it = g.plugins.begin(); it != g.plugins.end(); it++) { if ((*it)->id != id) continue; - uint8_t buf[sizeof(BoltIPCMessageTypeToClient) + sizeof(BoltIPCHostStoppedPluginHeader)]; - BoltIPCMessageTypeToClient* msg_type = reinterpret_cast(buf); - BoltIPCHostStoppedPluginHeader* header = reinterpret_cast(msg_type + 1); - *(BoltIPCMessageTypeToClient*)buf = IPC_MSG_HOST_STOPPED_PLUGIN; - *header = { .plugin_id = (*it)->uid }; - _bolt_ipc_send(g.fd, buf, sizeof(buf)); + const BoltIPCMessageTypeToClient msg_type = IPC_MSG_HOST_STOPPED_PLUGIN; + const BoltIPCHostStoppedPluginHeader header = { .plugin_id = (*it)->uid }; + this->send_lock.lock(); + _bolt_ipc_send(g.fd, &msg_type, sizeof(msg_type)); + _bolt_ipc_send(g.fd, &header, sizeof(header)); + this->send_lock.unlock(); (*it)->deleted = true; for (CefRefPtr& w: (*it)->windows_osr) { w->Close(); @@ -536,18 +536,14 @@ void Browser::Client::StartPlugin(uint64_t client_id, std::string id, std::strin } g.plugins.push_back(new ActivePlugin(this->next_plugin_uid, id, path, false)); - const size_t message_size = sizeof(BoltIPCMessageTypeToClient) + sizeof(BoltIPCStartPluginHeader) + path.size() + main.size(); - uint8_t* message = new uint8_t[message_size]; - BoltIPCMessageTypeToClient* msg_type = reinterpret_cast(message); - BoltIPCStartPluginHeader* header = reinterpret_cast(msg_type + 1); - uint8_t* message_path = reinterpret_cast(header + 1); - uint8_t* message_main = message_path + path.size(); - *msg_type = IPC_MSG_STARTPLUGIN; - *header = { .uid = this->next_plugin_uid, .path_size = static_cast(path.size()), .main_size = static_cast(main.size()) }; - memcpy(message_path, path.data(), path.size()); - memcpy(message_main, main.data(), main.size()); - _bolt_ipc_send(g.fd, message, message_size); - delete[] message; + const BoltIPCMessageTypeToClient msg_type = IPC_MSG_STARTPLUGIN; + const BoltIPCStartPluginHeader header = { .uid = this->next_plugin_uid, .path_size = static_cast(path.size()), .main_size = static_cast(main.size()) }; + this->send_lock.lock(); + _bolt_ipc_send(g.fd, &msg_type, sizeof(msg_type)); + _bolt_ipc_send(g.fd, &header, sizeof(header)); + _bolt_ipc_send(g.fd, path.data(), path.size()); + _bolt_ipc_send(g.fd, main.data(), main.size()); + this->send_lock.unlock(); this->next_plugin_uid += 1; break; } @@ -561,12 +557,12 @@ void Browser::Client::StopPlugin(uint64_t client_id, uint64_t uid) { if (!g.deleted && g.uid == client_id) { for (auto it = g.plugins.begin(); it != g.plugins.end(); it++) { if ((*it)->uid != uid) continue; - uint8_t buf[sizeof(BoltIPCMessageTypeToClient) + sizeof(BoltIPCHostStoppedPluginHeader)]; - BoltIPCMessageTypeToClient* msg_type = reinterpret_cast(buf); - BoltIPCHostStoppedPluginHeader* header = reinterpret_cast(msg_type + 1); - *(BoltIPCMessageTypeToClient*)buf = IPC_MSG_HOST_STOPPED_PLUGIN; - *header = { .plugin_id = (*it)->uid }; - _bolt_ipc_send(g.fd, buf, sizeof(buf)); + const BoltIPCMessageTypeToClient msg_type = IPC_MSG_HOST_STOPPED_PLUGIN; + const BoltIPCHostStoppedPluginHeader header = { .plugin_id = (*it)->uid }; + this->send_lock.lock(); + _bolt_ipc_send(g.fd, &msg_type, sizeof(msg_type)); + _bolt_ipc_send(g.fd, &header, sizeof(header)); + this->send_lock.unlock(); (*it)->deleted = true; for (CefRefPtr& w: (*it)->windows) { w->Close(); diff --git a/src/browser/client.hxx b/src/browser/client.hxx index ae099f9..e0d1971 100644 --- a/src/browser/client.hxx +++ b/src/browser/client.hxx @@ -177,6 +177,7 @@ namespace Browser { std::vector> plugins; }; + std::mutex send_lock; // would be great to have this per-GameClient but C++ doesn't like that std::thread ipc_thread; BoltSocketType ipc_fd; CefRefPtr ipc_view; diff --git a/src/browser/window_osr.cxx b/src/browser/window_osr.cxx index 018ec79..6750f41 100644 --- a/src/browser/window_osr.cxx +++ b/src/browser/window_osr.cxx @@ -16,24 +16,21 @@ #include "resource_handler.hxx" #include "../library/event.h" -static void SendUpdateMsg(BoltSocketType fd, uint64_t id, int width, int height, void* needs_remap, const CefRect* rects, uint32_t rect_count) { - const size_t bytes = sizeof(BoltIPCMessageTypeToClient) + sizeof(BoltIPCOsrUpdateHeader) + (rect_count * sizeof(BoltIPCOsrUpdateRect)); - uint8_t* buf = new uint8_t[bytes]; - BoltIPCMessageTypeToClient* msg_type = reinterpret_cast(buf); - BoltIPCOsrUpdateHeader* header = reinterpret_cast(msg_type + 1); - BoltIPCOsrUpdateRect* ipc_rects = reinterpret_cast(header + 1); - *msg_type = IPC_MSG_OSRUPDATE; - *header = { .rect_count = rect_count, .window_id = id, .needs_remap = needs_remap, .width = width, .height = height }; - +static void SendUpdateMsg(BoltSocketType fd, std::mutex* send_lock, uint64_t id, int width, int height, void* needs_remap, const CefRect* rects, uint32_t rect_count) { + const BoltIPCMessageTypeToClient msg_type = IPC_MSG_OSRUPDATE; + const BoltIPCOsrUpdateHeader header = { .rect_count = rect_count, .window_id = id, .needs_remap = needs_remap, .width = width, .height = height }; + send_lock->lock(); + _bolt_ipc_send(fd, &msg_type, sizeof(msg_type)); + _bolt_ipc_send(fd, &header, sizeof(header)); for (uint32_t i = 0; i < rect_count; i += 1) { - ipc_rects[i] = { .x = rects[i].x, .y = rects[i].y, .w = rects[i].width, .h = rects[i].height }; + const BoltIPCOsrUpdateRect rect = { .x = rects[i].x, .y = rects[i].y, .w = rects[i].width, .h = rects[i].height }; + _bolt_ipc_send(fd, &rect, sizeof(rect)); } - _bolt_ipc_send(fd, buf, bytes); - delete[] buf; + send_lock->unlock(); } -Browser::WindowOSR::WindowOSR(CefString url, int width, int height, BoltSocketType client_fd, Browser::Client* main_client, int pid, uint64_t window_id, uint64_t plugin_id, CefRefPtr file_manager): - PluginRequestHandler(IPC_MSG_OSRBROWSERMESSAGE), +Browser::WindowOSR::WindowOSR(CefString url, int width, int height, BoltSocketType client_fd, Browser::Client* main_client, std::mutex* send_lock, int pid, uint64_t window_id, uint64_t plugin_id, CefRefPtr file_manager): + PluginRequestHandler(IPC_MSG_OSRBROWSERMESSAGE, send_lock), deleted(false), pending_delete(false), client_fd(client_fd), width(width), height(height), browser(nullptr), window_id(window_id), plugin_id(plugin_id), main_client(main_client), stored(nullptr), remote_has_remapped(false), remote_is_idle(true), file_manager(file_manager) { @@ -99,12 +96,12 @@ CefRefPtr Browser::WindowOSR::Browser() const { } void Browser::WindowOSR::HandlePluginCloseRequest() { - uint8_t buf[sizeof(BoltIPCMessageTypeToClient) + sizeof(BoltIPCOsrCloseRequestHeader)]; - BoltIPCMessageTypeToClient* msg_type = reinterpret_cast(buf); - BoltIPCOsrCloseRequestHeader* header = reinterpret_cast(msg_type + 1); - *msg_type = IPC_MSG_OSRCLOSEREQUEST; - *header = { .window_id = this->window_id }; - _bolt_ipc_send(this->client_fd, buf, sizeof(buf)); + BoltIPCMessageTypeToClient msg_type = IPC_MSG_OSRCLOSEREQUEST; + BoltIPCOsrCloseRequestHeader header = { .window_id = this->window_id }; + this->send_lock->lock(); + _bolt_ipc_send(this->client_fd, &msg_type, sizeof(msg_type)); + _bolt_ipc_send(this->client_fd, &header, sizeof(header)); + this->send_lock->unlock(); } void Browser::WindowOSR::HandleAck() { @@ -129,7 +126,7 @@ void Browser::WindowOSR::HandleAck() { this->mapping_size = length; } memcpy(this->file, this->stored, length); - SendUpdateMsg(this->client_fd, this->window_id, this->stored_width, this->stored_height, needs_remap, &this->stored_damage, 1); + SendUpdateMsg(this->client_fd, this->send_lock, this->window_id, this->stored_width, this->stored_height, needs_remap, &this->stored_damage, 1); ::free(this->stored); this->stored = nullptr; } else { @@ -231,40 +228,36 @@ void Browser::WindowOSR::GetViewRect(CefRefPtr browser, CefRect& rec } void Browser::WindowOSR::OnPopupShow(CefRefPtr browser, bool show) { - uint8_t buf[sizeof(BoltIPCMessageTypeToClient) + sizeof(BoltIPCOsrPopupVisibilityHeader)]; - BoltIPCMessageTypeToClient* msg_type = reinterpret_cast(buf); - BoltIPCOsrPopupVisibilityHeader* header = reinterpret_cast(msg_type + 1); - *msg_type = IPC_MSG_OSRPOPUPVISIBILITY; - *header = { .window_id = this->WindowID(), .visible = show }; - _bolt_ipc_send(this->client_fd, buf, sizeof(buf)); + const BoltIPCMessageTypeToClient msg_type = IPC_MSG_OSRPOPUPVISIBILITY; + const BoltIPCOsrPopupVisibilityHeader header = { .window_id = this->WindowID(), .visible = show }; + this->send_lock->lock(); + _bolt_ipc_send(this->client_fd, &msg_type, sizeof(msg_type)); + _bolt_ipc_send(this->client_fd, &header, sizeof(header)); + this->send_lock->unlock(); } void Browser::WindowOSR::OnPopupSize(CefRefPtr browser, const CefRect& rect) { // Despite the function name, we don't actually use the size from here at all, we get that in OnPaint. // This function actually also gives us updates to the X and Y of the popup, which we do need. - uint8_t buf[sizeof(BoltIPCMessageTypeToClient) + sizeof(BoltIPCOsrPopupPositionHeader)]; - BoltIPCMessageTypeToClient* msg_type = reinterpret_cast(buf); - BoltIPCOsrPopupPositionHeader* header = reinterpret_cast(msg_type + 1); - *msg_type = IPC_MSG_OSRPOPUPPOSITION; - *header = { .window_id = this->WindowID(), .x = rect.x, .y = rect.y }; - _bolt_ipc_send(this->client_fd, buf, sizeof(buf)); + const BoltIPCMessageTypeToClient msg_type = IPC_MSG_OSRPOPUPPOSITION; + const BoltIPCOsrPopupPositionHeader header = { .window_id = this->WindowID(), .x = rect.x, .y = rect.y }; + this->send_lock->lock(); + _bolt_ipc_send(this->client_fd, &msg_type, sizeof(msg_type)); + _bolt_ipc_send(this->client_fd, &header, sizeof(header)); + this->send_lock->unlock(); } void Browser::WindowOSR::OnPaint(CefRefPtr browser, PaintElementType type, const RectList& dirtyRects, const void* buffer, int width, int height) { if (this->deleted || dirtyRects.empty()) return; if (type == PET_POPUP) { - const size_t rgba_bytes = width * height * 4; - const size_t bytes = sizeof(BoltIPCMessageTypeToClient) + sizeof(BoltIPCOsrPopupContentsHeader) + rgba_bytes; - uint8_t* buf = new uint8_t[bytes]; - BoltIPCMessageTypeToClient* msg_type = reinterpret_cast(buf); - BoltIPCOsrPopupContentsHeader* header = reinterpret_cast(msg_type + 1); - uint8_t* rgba = reinterpret_cast(header + 1); - *msg_type = IPC_MSG_OSRPOPUPCONTENTS; - *header = { .window_id = this->WindowID(), .width = width, .height = height }; - memcpy(rgba, buffer, rgba_bytes); - _bolt_ipc_send(this->client_fd, buf, bytes); - delete[] buf; + const BoltIPCMessageTypeToClient msg_type = IPC_MSG_OSRPOPUPCONTENTS; + const BoltIPCOsrPopupContentsHeader header = { .window_id = this->WindowID(), .width = width, .height = height }; + this->send_lock->lock(); + _bolt_ipc_send(this->client_fd, &msg_type, sizeof(msg_type)); + _bolt_ipc_send(this->client_fd, &header, sizeof(header)); + _bolt_ipc_send(this->client_fd, buffer, (size_t)width * (size_t)height * 4); + this->send_lock->unlock(); return; } @@ -305,7 +298,7 @@ void Browser::WindowOSR::OnPaint(CefRefPtr browser, PaintElementType needs_remap = (void*)1; #endif } - SendUpdateMsg(this->client_fd, this->window_id, width, height, needs_remap, dirtyRects.data(), dirtyRects.size()); + SendUpdateMsg(this->client_fd, this->send_lock, this->window_id, width, height, needs_remap, dirtyRects.data(), dirtyRects.size()); this->remote_has_remapped = true; this->remote_is_idle = false; } else { diff --git a/src/browser/window_osr.hxx b/src/browser/window_osr.hxx index 9c4df9d..2dc2202 100644 --- a/src/browser/window_osr.hxx +++ b/src/browser/window_osr.hxx @@ -23,7 +23,7 @@ namespace Browser { struct Client; struct WindowOSR: public CefClient, CefLifeSpanHandler, CefRenderHandler, PluginRequestHandler { - WindowOSR(CefString url, int width, int height, BoltSocketType client_fd, Client* main_client, int pid, uint64_t window_id, uint64_t plugin_id, CefRefPtr); + WindowOSR(CefString url, int width, int height, BoltSocketType client_fd, Client* main_client, std::mutex* send_lock, int pid, uint64_t window_id, uint64_t plugin_id, CefRefPtr); bool IsDeleted(); diff --git a/src/browser/window_plugin.cxx b/src/browser/window_plugin.cxx index a3d9286..281e10d 100644 --- a/src/browser/window_plugin.cxx +++ b/src/browser/window_plugin.cxx @@ -17,8 +17,9 @@ struct InitTask: public CefTask { DISALLOW_COPY_AND_ASSIGN(InitTask); }; -Browser::PluginWindow::PluginWindow(CefRefPtr main_client, Details details, const char* url, CefRefPtr file_manager, BoltSocketType fd, uint64_t id, uint64_t plugin_id, bool show_devtools): - PluginRequestHandler(IPC_MSG_EXTERNALBROWSERMESSAGE), Window(main_client, details, show_devtools), +Browser::PluginWindow::PluginWindow(CefRefPtr main_client, Details details, const char* url, CefRefPtr file_manager, BoltSocketType fd, std::mutex* send_lock, uint64_t id, uint64_t plugin_id, bool show_devtools): + PluginRequestHandler(IPC_MSG_EXTERNALBROWSERMESSAGE, send_lock), + Window(main_client, details, show_devtools), file_manager(file_manager), client_fd(fd), window_id(id), plugin_id(plugin_id), closing(false), deleted(false) { if (CefCurrentlyOn(TID_UI)) { @@ -53,12 +54,12 @@ CefRefPtr Browser::PluginWindow::Browser() const { } void Browser::PluginWindow::HandlePluginCloseRequest() { - uint8_t buf[sizeof(BoltIPCMessageTypeToClient) + sizeof(BoltIPCBrowserCloseRequestHeader)]; - BoltIPCMessageTypeToClient* msg_type = reinterpret_cast(buf); - BoltIPCBrowserCloseRequestHeader* header = reinterpret_cast(msg_type + 1); - *msg_type = IPC_MSG_BROWSERCLOSEREQUEST; - *header = { .window_id = this->window_id, .plugin_id = this->plugin_id }; - _bolt_ipc_send(this->client_fd, buf, sizeof(buf)); + const BoltIPCMessageTypeToClient msg_type = IPC_MSG_BROWSERCLOSEREQUEST; + const BoltIPCBrowserCloseRequestHeader header = { .window_id = this->window_id, .plugin_id = this->plugin_id }; + this->send_lock->lock(); + _bolt_ipc_send(this->client_fd, &msg_type, sizeof(msg_type)); + _bolt_ipc_send(this->client_fd, &header, sizeof(header)); + this->send_lock->unlock(); } bool Browser::PluginWindow::OnBeforePopup( diff --git a/src/browser/window_plugin.hxx b/src/browser/window_plugin.hxx index 356d399..f252288 100644 --- a/src/browser/window_plugin.hxx +++ b/src/browser/window_plugin.hxx @@ -8,7 +8,7 @@ namespace Browser { struct PluginWindow: public Window, PluginRequestHandler { - PluginWindow(CefRefPtr main_client, Details details, const char* url, CefRefPtr file_manager, BoltSocketType fd, uint64_t id, uint64_t plugin_id, bool show_devtools); + PluginWindow(CefRefPtr main_client, Details details, const char* url, CefRefPtr file_manager, BoltSocketType fd, std::mutex* send_lock, uint64_t id, uint64_t plugin_id, bool show_devtools); bool IsDeleted() const; uint64_t WindowID() const override; diff --git a/src/browser/window_plugin_requests.cxx b/src/browser/window_plugin_requests.cxx index 6161034..a0a1882 100644 --- a/src/browser/window_plugin_requests.cxx +++ b/src/browser/window_plugin_requests.cxx @@ -69,17 +69,16 @@ CefRefPtr Browser::PluginRequestHandler::GetResourceR CefPostData::ElementVector vec; post_data->GetElements(vec); size_t message_size = vec[0]->GetBytesCount(); - - const size_t bytes = sizeof(BoltIPCMessageTypeToClient) + sizeof(BoltIPCBrowserMessageHeader) + message_size; - uint8_t* buf = new uint8_t[bytes]; - BoltIPCMessageTypeToClient* msg_type = reinterpret_cast(buf); - BoltIPCBrowserMessageHeader* header = reinterpret_cast(msg_type + 1); - void* message = reinterpret_cast(header + 1); - *msg_type = this->message_type; - *header = {.window_id = this->WindowID(), .plugin_id = this->PluginID(), .message_size = message_size}; + uint8_t* message = new uint8_t[message_size]; vec[0]->GetBytes(message_size, message); - const uint8_t ret = _bolt_ipc_send(this->ClientFD(), buf, bytes); - delete[] buf; + + const BoltIPCBrowserMessageHeader header = { .window_id = this->WindowID(), .plugin_id = this->PluginID(), .message_size = message_size }; + this->send_lock->lock(); + const uint8_t ret = _bolt_ipc_send(this->ClientFD(), &this->message_type, sizeof(this->message_type)) + || _bolt_ipc_send(this->ClientFD(), &header, sizeof(header)) + || _bolt_ipc_send(this->ClientFD(), message, message_size); + this->send_lock->unlock(); + delete[] message; QSENDSYSTEMERRORIF(ret); QSENDOK(); } @@ -90,10 +89,8 @@ CefRefPtr Browser::PluginRequestHandler::GetResourceR } if (api_name == "start-reposition") { - uint8_t buf[sizeof(BoltIPCMessageTypeToClient) + sizeof(BoltIPCOsrStartRepositionHeader)]; - BoltIPCMessageTypeToClient* msg_type = reinterpret_cast(buf); - BoltIPCOsrStartRepositionHeader* header = reinterpret_cast(msg_type + 1); - *msg_type = IPC_MSG_OSRSTARTREPOSITION; + const BoltIPCMessageTypeToClient msg_type = IPC_MSG_OSRSTARTREPOSITION; + BoltIPCOsrStartRepositionHeader header; bool has_h = false; bool has_v = false; @@ -106,10 +103,13 @@ CefRefPtr Browser::PluginRequestHandler::GetResourceR QREQPARAMINT(h); QREQPARAMINT(v); - header->window_id = this->WindowID(); - header->horizontal = (h == 0) ? 0 : ((h > 0) ? 1 : -1); - header->vertical = (v == 0) ? 0 : ((v > 0) ? 1 : -1); - const uint8_t ret = _bolt_ipc_send(this->ClientFD(), buf, sizeof(buf)); + header.window_id = this->WindowID(); + header.horizontal = (h == 0) ? 0 : ((h > 0) ? 1 : -1); + header.vertical = (v == 0) ? 0 : ((v > 0) ? 1 : -1); + this->send_lock->lock(); + const uint8_t ret = _bolt_ipc_send(this->ClientFD(), &msg_type, sizeof(msg_type)) + || _bolt_ipc_send(this->ClientFD(), &header, sizeof(header)); + this->send_lock->unlock(); QSENDSYSTEMERRORIF(ret); QSENDOK(); } diff --git a/src/browser/window_plugin_requests.hxx b/src/browser/window_plugin_requests.hxx index 121a360..cc5484a 100644 --- a/src/browser/window_plugin_requests.hxx +++ b/src/browser/window_plugin_requests.hxx @@ -8,7 +8,7 @@ namespace Browser { /// Abstract class handling requests from plugin-managed browsers struct PluginRequestHandler: public CefRequestHandler { - PluginRequestHandler(BoltIPCMessageTypeToClient message_type): message_type(message_type) {} + PluginRequestHandler(BoltIPCMessageTypeToClient message_type, std::mutex* send_lock): message_type(message_type), send_lock(send_lock) {} void HandlePluginMessage(const uint8_t*, size_t); @@ -29,6 +29,9 @@ namespace Browser { virtual CefRefPtr Browser() const = 0; virtual void HandlePluginCloseRequest() = 0; + protected: + std::mutex* send_lock; + private: BoltIPCMessageTypeToClient message_type; };