diff --git a/docs/api/structures/web-preferences.md b/docs/api/structures/web-preferences.md index 047a13cefc2a..9c6a3ecc8fc8 100644 --- a/docs/api/structures/web-preferences.md +++ b/docs/api/structures/web-preferences.md @@ -74,7 +74,11 @@ * `defaultEncoding` string (optional) - Defaults to `ISO-8859-1`. * `backgroundThrottling` boolean (optional) - Whether to throttle animations and timers when the page becomes background. This also affects the - [Page Visibility API](../browser-window.md#page-visibility). Defaults to `true`. + [Page Visibility API](../browser-window.md#page-visibility). When at least one + [webContents](../web-contents.md) displayed in a single + [browserWindow](../browser-window.md) has disabled `backgroundThrottling` then + frames will be drawn and swapped for the whole window and other + [webContents](../web-contents.md) displayed by it. Defaults to `true`. * `offscreen` boolean (optional) - Whether to enable offscreen rendering for the browser window. Defaults to `false`. See the [offscreen rendering tutorial](../../tutorial/offscreen-rendering.md) for diff --git a/docs/breaking-changes.md b/docs/breaking-changes.md index b9ee818c8779..69492c43f290 100644 --- a/docs/breaking-changes.md +++ b/docs/breaking-changes.md @@ -14,6 +14,11 @@ This document uses the following convention to categorize breaking changes: ## Planned Breaking API Changes (28.0) +### Behavior Changed: `WebContents.backgroundThrottling` set to false affects all `WebContents` in the host `BrowserWindow` + +`WebContents.backgroundThrottling` set to false will disable frames throttling +in the `BrowserWindow` for all `WebContents` displayed by it. + ### Removed: `BrowserWindow.setTrafficLightPosition(position)` `BrowserWindow.setTrafficLightPosition(position)` has been removed, the diff --git a/filenames.gni b/filenames.gni index a9a1e4fcee19..74094b744b5c 100644 --- a/filenames.gni +++ b/filenames.gni @@ -339,6 +339,7 @@ filenames = { "shell/browser/api/ui_event.h", "shell/browser/auto_updater.cc", "shell/browser/auto_updater.h", + "shell/browser/background_throttling_source.h", "shell/browser/badging/badge_manager.cc", "shell/browser/badging/badge_manager.h", "shell/browser/badging/badge_manager_factory.cc", diff --git a/patches/chromium/.patches b/patches/chromium/.patches index 515db1987273..58425d281b5c 100644 --- a/patches/chromium/.patches +++ b/patches/chromium/.patches @@ -124,6 +124,7 @@ feat_expose_documentloader_setdefersloading_on_webdocumentloader.patch fix_remove_profiles_from_spellcheck_service.patch chore_patch_out_profile_methods_in_chrome_browser_pdf.patch chore_patch_out_profile_methods_in_titlebar_config.patch +fix_disabling_background_throttling_in_compositor.patch fix_select_the_first_menu_item_when_opened_via_keyboard.patch fix_return_v8_value_from_localframe_requestexecutescript.patch fix_harden_blink_scriptstate_maybefrom.patch diff --git a/patches/chromium/fix_disabling_background_throttling_in_compositor.patch b/patches/chromium/fix_disabling_background_throttling_in_compositor.patch new file mode 100644 index 000000000000..6c9704744402 --- /dev/null +++ b/patches/chromium/fix_disabling_background_throttling_in_compositor.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michal Pichlinski +Date: Thu, 15 Jun 2023 23:04:48 +0200 +Subject: allow disabling throttling in the `viz::DisplayScheduler` per + `ui::Compositor` + +In Chromium when the `viz::DisplayScheduler` is invisible it throttles +its work by dropping frame draws and swaps. + +This patch allows disbling this throttling by preventing transition to +invisible state of the `viz::DisplayScheduler` owned +by the `ui::Compositor`. + +diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc +index 623991465edb99ee720c8177c3511e4d025ed890..c94537af56f7de8cd15bd3b3155b79b41ea003f4 100644 +--- a/ui/compositor/compositor.cc ++++ b/ui/compositor/compositor.cc +@@ -341,7 +341,8 @@ void Compositor::SetLayerTreeFrameSink( + if (display_private_) { + disabled_swap_until_resize_ = false; + display_private_->Resize(size()); +- display_private_->SetDisplayVisible(host_->IsVisible()); ++ // Invisible display is throttling itself. ++ display_private_->SetDisplayVisible(background_throttling_ ? host_->IsVisible() : true); + display_private_->SetDisplayColorSpaces(display_color_spaces_); + display_private_->SetDisplayColorMatrix( + gfx::SkM44ToTransform(display_color_matrix_)); +@@ -533,8 +534,11 @@ void Compositor::SetVisible(bool visible) { + host_->SetVisible(visible); + // Visibility is reset when the output surface is lost, so this must also be + // updated then. +- if (display_private_) +- display_private_->SetDisplayVisible(visible); ++ if (display_private_) { ++ // Invisible display is throttling itself. ++ display_private_->SetDisplayVisible( ++ background_throttling_ ? visible : true); ++ } + } + + bool Compositor::IsVisible() { +@@ -959,4 +963,13 @@ const cc::LayerTreeSettings& Compositor::GetLayerTreeSettings() const { + return host_->GetSettings(); + } + ++void Compositor::SetBackgroundThrottling(bool background_throttling_enabled) { ++ background_throttling_ = background_throttling_enabled; ++ if (display_private_) { ++ // Invisible display is throttling itself. ++ display_private_->SetDisplayVisible( ++ background_throttling_ ? host_->IsVisible() : true); ++ } ++} ++ + } // namespace ui +diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h +index ddb28fd6f7549759df7e3b7d6b309cd982e199af..7473f3af9bc8cac8db3c30dfbc9b7140f832ac15 100644 +--- a/ui/compositor/compositor.h ++++ b/ui/compositor/compositor.h +@@ -511,6 +511,10 @@ class COMPOSITOR_EXPORT Compositor : public base::PowerSuspendObserver, + + const cc::LayerTreeSettings& GetLayerTreeSettings() const; + ++ // Sets |background_throttling_| responsible for suspending drawing ++ // and switching frames. ++ void SetBackgroundThrottling(bool background_throttling_enabled); ++ + private: + friend class base::RefCounted; + friend class TotalAnimationThroughputReporter; +@@ -617,6 +621,12 @@ class COMPOSITOR_EXPORT Compositor : public base::PowerSuspendObserver, + // See go/report-ux-metrics-at-painting for details. + bool animation_started_ = false; + ++ // Background throttling is a default Chromium behaviour. It occurs ++ // when the |display_private_| is not visible by prevent drawing and swapping ++ // frames. When it is disabled we are keeping |display_private_| always ++ // visible in order to keep generating frames. ++ bool background_throttling_ = true; ++ + TrackerId next_throughput_tracker_id_ = 1u; + struct TrackerState { + TrackerState(); diff --git a/shell/browser/api/electron_api_web_contents.cc b/shell/browser/api/electron_api_web_contents.cc index bcd8e4037303..d820fb8ba693 100644 --- a/shell/browser/api/electron_api_web_contents.cc +++ b/shell/browser/api/electron_api_web_contents.cc @@ -1029,6 +1029,9 @@ void WebContents::InitWithWebContents( } WebContents::~WebContents() { + if (owner_window_) { + owner_window_->RemoveBackgroundThrottlingSource(this); + } if (web_contents()) { content::RenderViewHost* host = web_contents()->GetRenderViewHost(); if (host) @@ -2226,10 +2229,15 @@ void WebContents::SetOwnerWindow(NativeWindow* owner_window) { void WebContents::SetOwnerWindow(content::WebContents* web_contents, NativeWindow* owner_window) { + if (owner_window_) { + owner_window_->RemoveBackgroundThrottlingSource(this); + } + if (owner_window) { owner_window_ = owner_window->GetWeakPtr(); NativeWindowRelay::CreateForWebContents(web_contents, owner_window->GetWeakPtr()); + owner_window_->AddBackgroundThrottlingSource(this); } else { owner_window_ = nullptr; web_contents->RemoveUserData(NativeWindowRelay::UserDataKey()); @@ -2283,6 +2291,10 @@ bool WebContents::GetBackgroundThrottling() const { void WebContents::SetBackgroundThrottling(bool allowed) { background_throttling_ = allowed; + if (owner_window_) { + owner_window_->UpdateBackgroundThrottlingState(); + } + auto* rfh = web_contents()->GetPrimaryMainFrame(); if (!rfh) return; diff --git a/shell/browser/api/electron_api_web_contents.h b/shell/browser/api/electron_api_web_contents.h index fb47ebb90431..c65e743c002c 100644 --- a/shell/browser/api/electron_api_web_contents.h +++ b/shell/browser/api/electron_api_web_contents.h @@ -36,6 +36,7 @@ #include "printing/buildflags/buildflags.h" #include "shell/browser/api/frame_subscriber.h" #include "shell/browser/api/save_page_handler.h" +#include "shell/browser/background_throttling_source.h" #include "shell/browser/event_emitter_mixin.h" #include "shell/browser/extended_web_contents_observer.h" #include "shell/browser/ui/inspectable_web_contents.h" @@ -107,7 +108,8 @@ class WebContents : public ExclusiveAccessContext, public content::WebContentsDelegate, public content::RenderWidgetHost::InputEventObserver, public InspectableWebContentsDelegate, - public InspectableWebContentsViewDelegate { + public InspectableWebContentsViewDelegate, + public BackgroundThrottlingSource { public: enum class Type { kBackgroundPage, // An extension background page. @@ -160,7 +162,7 @@ class WebContents : public ExclusiveAccessContext, void Close(absl::optional options); base::WeakPtr GetWeakPtr() { return weak_factory_.GetWeakPtr(); } - bool GetBackgroundThrottling() const; + bool GetBackgroundThrottling() const override; void SetBackgroundThrottling(bool allowed); int GetProcessID() const; base::ProcessId GetOSProcessID() const; diff --git a/shell/browser/background_throttling_source.h b/shell/browser/background_throttling_source.h new file mode 100644 index 000000000000..783f58230edf --- /dev/null +++ b/shell/browser/background_throttling_source.h @@ -0,0 +1,18 @@ +// Copyright 2023 OpenFin. All rights reserved. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ELECTRON_SHELL_BROWSER_BACKGROUND_THROTTLING_SOURCE +#define ELECTRON_SHELL_BROWSER_BACKGROUND_THROTTLING_SOURCE + +namespace electron { + +class BackgroundThrottlingSource { + public: + virtual ~BackgroundThrottlingSource() = default; + virtual bool GetBackgroundThrottling() const = 0; +}; + +} // namespace electron + +#endif // ELECTRON_SHELL_BROWSER_BACKGROUND_THROTTLING_SOURCE diff --git a/shell/browser/native_window.cc b/shell/browser/native_window.cc index 9b3d8b24e20c..d775c635bc2d 100644 --- a/shell/browser/native_window.cc +++ b/shell/browser/native_window.cc @@ -14,6 +14,7 @@ #include "base/values.h" #include "content/public/browser/web_contents_user_data.h" #include "include/core/SkColor.h" +#include "shell/browser/background_throttling_source.h" #include "shell/browser/browser.h" #include "shell/browser/native_window_features.h" #include "shell/browser/ui/drag_util.h" @@ -24,6 +25,7 @@ #include "shell/common/options_switches.h" #include "third_party/skia/include/core/SkRegion.h" #include "ui/base/hit_test.h" +#include "ui/compositor/compositor.h" #include "ui/views/widget/widget.h" #if !BUILDFLAG(IS_MAC) @@ -767,6 +769,37 @@ void NativeWindow::RemoveDraggableRegionProvider( [&provider](DraggableRegionProvider* p) { return p == provider; }); } +void NativeWindow::AddBackgroundThrottlingSource( + BackgroundThrottlingSource* source) { + auto result = background_throttling_sources_.insert(source); + DCHECK(result.second) << "Added already stored BackgroundThrottlingSource."; + UpdateBackgroundThrottlingState(); +} + +void NativeWindow::RemoveBackgroundThrottlingSource( + BackgroundThrottlingSource* source) { + auto result = background_throttling_sources_.erase(source); + DCHECK(result == 1) + << "Tried to remove non existing BackgroundThrottlingSource."; + UpdateBackgroundThrottlingState(); +} + +void NativeWindow::UpdateBackgroundThrottlingState() { + if (!GetWidget() || !GetWidget()->GetCompositor()) { + return; + } + bool enable_background_throttling = true; + for (const auto* background_throttling_source : + background_throttling_sources_) { + if (!background_throttling_source->GetBackgroundThrottling()) { + enable_background_throttling = false; + break; + } + } + GetWidget()->GetCompositor()->SetBackgroundThrottling( + enable_background_throttling); +} + views::Widget* NativeWindow::GetWidget() { return widget(); } diff --git a/shell/browser/native_window.h b/shell/browser/native_window.h index a091c834f7f3..d2ec3c9fe9e7 100644 --- a/shell/browser/native_window.h +++ b/shell/browser/native_window.h @@ -47,6 +47,7 @@ class PersistentDictionary; namespace electron { class ElectronMenuModel; +class BackgroundThrottlingSource; class NativeBrowserView; namespace api { @@ -401,6 +402,17 @@ class NativeWindow : public base::SupportsUserData, bool IsTranslucent() const; + // Adds |source| to |background_throttling_sources_|, triggers update of + // background throttling state. + void AddBackgroundThrottlingSource(BackgroundThrottlingSource* source); + // Removes |source| to |background_throttling_sources_|, triggers update of + // background throttling state. + void RemoveBackgroundThrottlingSource(BackgroundThrottlingSource* source); + // Updates `ui::Compositor` background throttling state based on + // |background_throttling_sources_|. If at least one of the sources disables + // throttling, then throttling in the `ui::Compositor` will be disabled. + void UpdateBackgroundThrottlingState(); + protected: friend class api::BrowserView; @@ -495,6 +507,8 @@ class NativeWindow : public base::SupportsUserData, // Observers of this window. base::ObserverList observers_; + std::set background_throttling_sources_; + // Accessible title. std::u16string accessible_title_;