ungoogled-software / ungoogled-chromium

Google Chromium, sans integration with Google
BSD 3-Clause "New" or "Revised" License
20.34k stars 823 forks source link

Update to Chromium 125.0.6422.76 #2875

Closed Ahrotahn closed 4 months ago

Ahrotahn commented 4 months ago

This PR updates to Chromium 125.0.6422.76 There were no notable changes needed on our end.


Change log Blog post

Ahrotahn commented 4 months ago

There's a bug between Chromium and KDE Plasma 6 when using wayland that causes input (except for the scrollwheel) to hang after something has been dragged. This has been fixed in [5539621] (and !5738) but doesn't land until 126. I've adjusted the patch to work for 125 since I've encountered this issue a few times, and I figured I'd share the changes if its useful to anyone else:

diff ```diff # From d0f2e2e872e8fc67fbaacb14626e0bc30759dd31 Mon Sep 17 00:00:00 2001 # From: Nick Diego Yamane # Date: Wed, 15 May 2024 16:36:17 +0000 # Subject: [PATCH] wayland: factor HandleDragEnd out of Reset in data drag controller # # The nested message loop used for outgoing drag sessions should be tied # to the dnd_drop_performed event rather than the whole underlying drag # flow, which includes async wl_data_source events, such as, dnd_finished # and cancelled. Further details can be found at analysis [1]. # # Another effect of this change is that it works as a mitigation to # prevent browser process from hanging, ie: stopping to respond to input # events caused by an never ending drag-and-drop loop when dealing with # misbehaving/buggy or malicious Wayland compositors. A real case of this # was found in the wild with some versions of Kwin 6, as described in the # linked crbugs. # # [1] https://notes.nickdiego.dev/chromium/wayland-events-during-drag # # Bug: 329479345, 336449364, 325741108 # Change-Id: Ib4757223ce9e490c2a65999da77bf1257f7fc3ae # Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5539621 # Commit-Queue: Nick Yamane # Reviewed-by: Max Ihlenfeldt # Reviewed-by: Orko Garai # Cr-Commit-Position: refs/heads/main@{#1301363} --- a/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc +++ b/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc @@ -125,9 +125,13 @@ WaylandDataDragController::~WaylandDataD bool WaylandDataDragController::StartSession(const OSExchangeData& data, int operations, DragEventSource source) { - DCHECK_EQ(state_, State::kIdle); - DCHECK(!origin_window_); - DCHECK(!icon_surface_); + // TODO(crbug.com/340398746): Should be DCHECK'ed instead, though due to buggy + // compositors, eg: KWin 6, which do not send data_source.dnd_finish|cancelled + // in some cases, it was temporarily turned into this conditional avoid + // browser crashes. Revert once it stabilizes at compositors side. + if (state_ != State::kIdle) { + Reset(); + } auto* origin_window = source == DragEventSource::kTouch ? window_manager_->GetCurrentTouchFocusedWindow() @@ -213,7 +217,8 @@ void WaylandDataDragController::CancelSe // deferring the reset (e.g. until we receive wl_data_device.leave) in turn // might lead to issues for real users if the compositor implements the spec // incorrectly or just in a way we didn't foresee. - Reset(DragResult::kCancelled, ui::EventTimeForNow()); + HandleDragEnd(DragResult::kCancelled, ui::EventTimeForNow()); + Reset(); } void WaylandDataDragController::UpdateDragImage(const gfx::ImageSkia& image, @@ -507,8 +512,25 @@ void WaylandDataDragController::OnDataSo << " origin=" << !!origin_window_ << " nested_dispatcher=" << !!nested_dispatcher_; - auto result = completed ? DragResult::kCompleted : DragResult::kCancelled; - Reset(result, timestamp); + // HandleDragEnd below is likely no-op, though is called to protect against + // buggy/malicious compositors, where no prior dnd_drop_performed was + // received, for example. In which case, it could result in UI hangs where + // input events would stop being processed because the nested drag message + // loop would keep running indefinitely. + HandleDragEnd(completed ? DragResult::kCompleted : DragResult::kCancelled, + timestamp); + Reset(); +} + +void WaylandDataDragController::OnDataSourceDropPerformed( + WaylandDataSource* source, + base::TimeTicks timestamp) { + CHECK_EQ(data_source_.get(), source); + VLOG(1) << __FUNCTION__ << " window=" << !!window_ + << " origin=" << !!origin_window_ + << " nested_dispatcher=" << !!nested_dispatcher_; + + HandleDragEnd(DragResult::kCompleted, timestamp); } const WaylandWindow* WaylandDataDragController::GetDragTarget() const { @@ -654,12 +676,29 @@ void WaylandDataDragController::CancelDa } } -void WaylandDataDragController::Reset(DragResult result, - base::TimeTicks timestamp) { +void WaylandDataDragController::Reset() { if (state_ == State::kIdle) { return; } + data_source_.reset(); + data_offer_.reset(); + icon_buffer_.reset(); + icon_surface_.reset(); + icon_surface_buffer_scale_ = 1.0f; + icon_image_ = gfx::ImageSkia(); + icon_frame_callback_.reset(); + offered_exchange_data_provider_.reset(); + data_device_->ResetDragDelegate(); + has_received_enter_ = false; + state_ = State::kIdle; +} + +// TODO(crbug.com/329479345): Drop DragResult in favor of intermediary states +// `kDropping` and `kCancelling`, move `Reset` back into this function, called +// conditionally depending on the state it would be transitioning to. +void WaylandDataDragController::HandleDragEnd(DragResult result, + base::TimeTicks timestamp) { if (origin_window_) { DragOperation operation = (result == DragResult::kCompleted) @@ -684,18 +723,6 @@ void WaylandDataDragController::Reset(Dr if (pointer_grabber_for_window_drag_) { DispatchPointerRelease(timestamp); } - - data_source_.reset(); - data_offer_.reset(); - icon_buffer_.reset(); - icon_surface_.reset(); - icon_surface_buffer_scale_ = 1.0f; - icon_image_ = gfx::ImageSkia(); - icon_frame_callback_.reset(); - offered_exchange_data_provider_.reset(); - data_device_->ResetDragDelegate(); - has_received_enter_ = false; - state_ = State::kIdle; } std::optional @@ -782,7 +809,8 @@ uint32_t WaylandDataDragController::Disp // once. if (event->type() == ET_MOUSE_RELEASED) { if (!has_received_enter_) { - Reset(DragResult::kCancelled, event->time_stamp()); + HandleDragEnd(DragResult::kCancelled, event->time_stamp()); + Reset(); } else { return POST_DISPATCH_STOP_PROPAGATION; } --- a/ui/ozone/platform/wayland/host/wayland_data_drag_controller.h +++ b/ui/ozone/platform/wayland/host/wayland_data_drag_controller.h @@ -164,6 +164,8 @@ class WaylandDataDragController : public void OnDataSourceFinish(WaylandDataSource* source, base::TimeTicks timestamp, bool completed) override; + void OnDataSourceDropPerformed(WaylandDataSource* source, + base::TimeTicks timestamp) override; void OnDataSourceSend(WaylandDataSource* source, const std::string& mime_type, std::string* contents) override; @@ -184,9 +186,14 @@ class WaylandDataDragController : public std::unique_ptr received_data); void CancelDataFetchingIfNeeded(); - // Completes/cancels the drag session and resets everything to idle state. - // Does nothing if the current state is already `kIdle`. - void Reset(DragResult result, base::TimeTicks timestamp); + // Resets everything to idle state. Does nothing if the current state is + // already `kIdle`. + void Reset(); + + // Perform steps required when ending a drag session. e.g: quit the nested + // drag loop (if any), remove the event dispatcher override, and notify the + // drag/drop handlers based on `result`. + void HandleDragEnd(DragResult result, base::TimeTicks timestamp); std::optional GetAndValidateSerialForDrag( mojom::DragEventSource source); --- a/ui/ozone/platform/wayland/host/wayland_data_source.cc +++ b/ui/ozone/platform/wayland/host/wayland_data_source.cc @@ -37,6 +37,13 @@ DataSource::~DataSource() { } template +void DataSource::HandleDropEvent() { + VLOG(1) << "OnDataSourceDropPerformed in WaylandDataSource"; + // No timestamp for these events. Use EventTimeForNow(), for now. + delegate_->OnDataSourceDropPerformed(this, ui::EventTimeForNow()); +} + +template void DataSource::HandleFinishEvent(bool completed) { VLOG(1) << "OnDataSourceFinish in WaylandDataSource"; // No timestamp for these events. Use EventTimeForNow(), for now. @@ -108,7 +115,8 @@ void DataSource::OnTarget(void* data, template void DataSource::OnDndDropPerformed(void* data, T* source) { - NOTIMPLEMENTED_LOG_ONCE(); + auto* self = static_cast*>(data); + self->HandleDropEvent(); } ////////////////////////////////////////////////////////////////////////////// --- a/ui/ozone/platform/wayland/host/wayland_data_source.h +++ b/ui/ozone/platform/wayland/host/wayland_data_source.h @@ -11,6 +11,7 @@ #include "base/memory/raw_ptr.h" #include "base/notreached.h" +#include "base/time/time.h" #include "ui/ozone/platform/wayland/common/wayland_object.h" struct wl_data_source; @@ -64,6 +65,10 @@ class DataSource { virtual void OnDataSourceSend(DataSource* source, const std::string& mime_type, std::string* contents) = 0; + // Optional callback intended to be implemented only by dnd-capable delegate + // implementations. + virtual void OnDataSourceDropPerformed(DataSource* source, + base::TimeTicks timestamp) {} protected: virtual ~Delegate() = default; @@ -86,6 +91,7 @@ class DataSource { private: void HandleFinishEvent(bool completed); + void HandleDropEvent(); void HandleSendEvent(const std::string& mime_type, int32_t fd); // {T}_listener callbacks: # Due to not having all prior changes, fallback to simplified drag --- a/chrome/browser/ui/ui_features.cc +++ b/chrome/browser/ui/ui_features.cc @@ -17,7 +17,7 @@ // by the platform (e.g. Wayland). See https://crbug.com/896640 BASE_FEATURE(kAllowWindowDragUsingSystemDragDrop, "AllowWindowDragUsingSystemDragDrop", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); // Enables the use of WGC for the Eye Dropper screen capture. BASE_FEATURE(kAllowEyeDropperWGCScreenCapture, ```
clickot commented 4 months ago

portable linux builds fine and runs at least on manjaro and ubuntu 20.04/24.04