Browse Source

fix: BrowserView background color in webContents (#33478)

* chore: fix BrowserView background color in webContents

* disable screen capture test on linux

* spec: fix platform failure condition

Co-authored-by: Shelley Vohr <[email protected]>
trop[bot] 2 years ago
parent
commit
3823245a46

+ 18 - 1
shell/browser/api/electron_api_browser_view.cc

@@ -6,10 +6,13 @@
 
 #include <vector>
 
+#include "content/browser/renderer_host/render_widget_host_view_base.h"  // nogncheck
+#include "content/public/browser/render_widget_host_view.h"
 #include "shell/browser/api/electron_api_web_contents.h"
 #include "shell/browser/browser.h"
 #include "shell/browser/native_browser_view.h"
 #include "shell/browser/ui/drag_util.h"
+#include "shell/browser/web_contents_preferences.h"
 #include "shell/common/color_util.h"
 #include "shell/common/gin_converters/gfx_converter.h"
 #include "shell/common/gin_helper/dictionary.h"
@@ -154,11 +157,25 @@ gfx::Rect BrowserView::GetBounds() {
 }
 
 void BrowserView::SetBackgroundColor(const std::string& color_name) {
-  view_->SetBackgroundColor(ParseCSSColor(color_name));
+  SkColor color = ParseCSSColor(color_name);
+  view_->SetBackgroundColor(color);
 
   if (web_contents()) {
     auto* wc = web_contents()->web_contents();
     wc->SetPageBaseBackgroundColor(ParseCSSColor(color_name));
+
+    auto* const rwhv = wc->GetRenderWidgetHostView();
+    if (rwhv) {
+      rwhv->SetBackgroundColor(color);
+      static_cast<content::RenderWidgetHostViewBase*>(rwhv)
+          ->SetContentBackgroundColor(color);
+    }
+
+    // Ensure new color is stored in webPreferences, otherwise
+    // the color will be reset on the next load via HandleNewRenderFrame.
+    auto* web_preferences = WebContentsPreferences::From(wc);
+    if (web_preferences)
+      web_preferences->SetBackgroundColor(color);
   }
 }
 

+ 6 - 4
shell/browser/api/electron_api_web_contents.cc

@@ -1495,11 +1495,13 @@ void WebContents::HandleNewRenderFrame(
   // Set the background color of RenderWidgetHostView.
   auto* web_preferences = WebContentsPreferences::From(web_contents());
   if (web_preferences) {
+    absl::optional<SkColor> maybe_color = web_preferences->GetBackgroundColor();
+    web_contents()->SetPageBaseBackgroundColor(maybe_color);
+
     bool guest = IsGuest() || type_ == Type::kBrowserView;
-    absl::optional<SkColor> color =
-        guest ? SK_ColorTRANSPARENT : web_preferences->GetBackgroundColor();
-    web_contents()->SetPageBaseBackgroundColor(color);
-    SetBackgroundColor(rwhv, color.value_or(SK_ColorWHITE));
+    SkColor color =
+        maybe_color.value_or(guest ? SK_ColorTRANSPARENT : SK_ColorWHITE);
+    SetBackgroundColor(rwhv, color);
   }
 
   if (!background_throttling_)

+ 53 - 2
spec-main/api-browser-view-spec.ts

@@ -1,9 +1,10 @@
 import { expect } from 'chai';
 import * as path from 'path';
 import { emittedOnce } from './events-helpers';
-import { BrowserView, BrowserWindow, webContents } from 'electron/main';
+import { BrowserView, BrowserWindow, screen, webContents } from 'electron/main';
 import { closeWindow } from './window-helpers';
-import { defer, startRemoteControlApp } from './spec-helpers';
+import { defer, ifit, startRemoteControlApp } from './spec-helpers';
+import { areColorsSimilar, captureScreen, getPixelColor } from './screen-helpers';
 
 describe('BrowserView module', () => {
   const fixtures = path.resolve(__dirname, '..', 'spec', 'fixtures');
@@ -60,6 +61,56 @@ describe('BrowserView module', () => {
         view.setBackgroundColor(null as any);
       }).to.throw(/conversion failure/);
     });
+
+    // Linux and arm64 platforms (WOA and macOS) do not return any capture sources
+    ifit(process.platform !== 'linux' && process.arch !== 'arm64')('sets the background color to transparent if none is set', async () => {
+      const display = screen.getPrimaryDisplay();
+      const WINDOW_BACKGROUND_COLOR = '#55ccbb';
+
+      w.show();
+      w.setBounds(display.bounds);
+      w.setBackgroundColor(WINDOW_BACKGROUND_COLOR);
+      await w.loadURL('about:blank');
+
+      view = new BrowserView();
+      view.setBounds(display.bounds);
+      w.setBrowserView(view);
+      await view.webContents.loadURL('data:text/html,hello there');
+
+      const screenCapture = await captureScreen();
+      const centerColor = getPixelColor(screenCapture, {
+        x: display.size.width / 2,
+        y: display.size.height / 2
+      });
+
+      expect(areColorsSimilar(centerColor, WINDOW_BACKGROUND_COLOR)).to.be.true();
+    });
+
+    // Linux and arm64 platforms (WOA and macOS) do not return any capture sources
+    ifit(process.platform !== 'linux' && process.arch !== 'arm64')('successfully applies the background color', async () => {
+      const WINDOW_BACKGROUND_COLOR = '#55ccbb';
+      const VIEW_BACKGROUND_COLOR = '#ff00ff';
+      const display = screen.getPrimaryDisplay();
+
+      w.show();
+      w.setBounds(display.bounds);
+      w.setBackgroundColor(WINDOW_BACKGROUND_COLOR);
+      await w.loadURL('about:blank');
+
+      view = new BrowserView();
+      view.setBounds(display.bounds);
+      w.setBrowserView(view);
+      w.setBackgroundColor(VIEW_BACKGROUND_COLOR);
+      await view.webContents.loadURL('data:text/html,hello there');
+
+      const screenCapture = await captureScreen();
+      const centerColor = getPixelColor(screenCapture, {
+        x: display.size.width / 2,
+        y: display.size.height / 2
+      });
+
+      expect(areColorsSimilar(centerColor, VIEW_BACKGROUND_COLOR)).to.be.true();
+    });
   });
 
   describe('BrowserView.setAutoResize()', () => {