fix: disable background throttling also in the viz::DisplayScheduler (#38924)
		
	* fix: disable background throttling also in the `viz::DisplayScheduler` `viz::DisplayScheduler` is responsible for drawing and swapping frames in the `DisplayScheduler::DrawAndSwap` which is called from the `DisplayScheduler::AttemptDrawAndSwap` if the `DisplayScheduler::ShouldDraw` returns true. `ShouldDraw` depends on the `DisplayScheduler` visibility and when it is not visible then it returns false. In order to keep producing frames, disabling `backgroundThrottling` should also prevent changing `DisplayScheduler` visibility to false. `DisplayScheduler` lives in the `ui::Compositor` where every `electron::NativewWindow` has its own `Compositor`. `electron::NativewWindow` may be host of the multiple `electron::api::WebContents` instances which may have different `WebPreferences` settings. Therefore if at least one of the `WebContents` requires disabling throttling then all other `WebContents` using the same window will have it disabled in the `ui::Compositor`. BREAKING CHANGE: `backgroundThrottling` set to false will disable frames throttling in the `BrowserWindow` for all `WebContents` displayed by it. Close: [#31016](https://github.com/electron/electron/issues/31016) * fixup! fix: disable background throttling also in the `viz::DisplayScheduler` * fixup! fix: disable background throttling also in the `viz::DisplayScheduler` * fixup! fix: disable background throttling also in the `viz::DisplayScheduler` --------- Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
This commit is contained in:
		
					parent
					
						
							
								fa215f1009
							
						
					
				
			
			
				commit
				
					
						2190793fe6
					
				
			
		
					 10 changed files with 176 additions and 3 deletions
				
			
		| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,83 @@
 | 
			
		|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Michal Pichlinski <michal.pichlinski@openfin.co>
 | 
			
		||||
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<Compositor>;
 | 
			
		||||
   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();
 | 
			
		||||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<gin_helper::Dictionary> options);
 | 
			
		||||
  base::WeakPtr<WebContents> GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
 | 
			
		||||
 | 
			
		||||
  bool GetBackgroundThrottling() const;
 | 
			
		||||
  bool GetBackgroundThrottling() const override;
 | 
			
		||||
  void SetBackgroundThrottling(bool allowed);
 | 
			
		||||
  int GetProcessID() const;
 | 
			
		||||
  base::ProcessId GetOSProcessID() const;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										18
									
								
								shell/browser/background_throttling_source.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								shell/browser/background_throttling_source.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<NativeWindowObserver> observers_;
 | 
			
		||||
 | 
			
		||||
  std::set<BackgroundThrottlingSource*> background_throttling_sources_;
 | 
			
		||||
 | 
			
		||||
  // Accessible title.
 | 
			
		||||
  std::u16string accessible_title_;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue