Browse Source

fix: ensure child window transparency works (#28054)

* fix: ensure child window transparency works

Windows opened via window.open and intecepted via setWindowOpenHandler
or the `new-window` event should (a) have the correct background color
and (b) that background color should be transparent if specified.

The changes in api_web_contents fix (a) and the changes in
web_contents_preferences fix (b).

Notes: Child windows with specified background colors or transpency now
work as intended

* fix: set background_color in blink prefs apply logic

* chore: update for PR comments
Samuel Attard 4 years ago
parent
commit
089ac8180f

+ 1 - 0
lib/browser/api/web-contents.ts

@@ -588,6 +588,7 @@ WebContents.prototype._init = function () {
           // it's technically a BrowserWindowConstructorOptions option because
           // we need to access it in the renderer at init time.
           backgroundColor: windowOpenOverriddenOptions.backgroundColor,
+          transparent: windowOpenOverriddenOptions.transparent,
           ...windowOpenOverriddenOptions.webPreferences
         } : undefined;
         this._setNextChildWebPreferences(

+ 1 - 0
patches/chromium/.patches

@@ -108,3 +108,4 @@ add_trustedauthclient_to_urlloaderfactory.patch
 fix_route_mouse_event_navigations_through_the_web_contents_delegate.patch
 disable_unload_metrics.patch
 fix_add_check_for_sandbox_then_result.patch
+moves_background_color_setter_of_webview_to_blinks_webprefs_logic.patch

+ 40 - 0
patches/chromium/moves_background_color_setter_of_webview_to_blinks_webprefs_logic.patch

@@ -0,0 +1,40 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Samuel Attard <[email protected]>
+Date: Mon, 8 Mar 2021 16:27:39 -0800
+Subject: moves background_color setter of WebView to blinks webprefs logic
+
+background_color can be updated at runtime, as such we need to apply the
+new background color to the WebView in the ApplyPreferences method.
+There is no current way to attach an observer to these prefs so patching
+is our only option.
+
+Ideally we could add an embedder observer pattern here but that can be
+done in future work.
+
+diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc
+index fb994344ea53e17df84f176ad7d8722793b72cfd..fb3d42378d1ec2611c3c2055f96380e3a9873847 100644
+--- a/third_party/blink/renderer/core/exported/web_view_impl.cc
++++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
+@@ -154,6 +154,7 @@
+ #include "third_party/blink/renderer/core/timing/dom_window_performance.h"
+ #include "third_party/blink/renderer/core/timing/window_performance.h"
+ #include "third_party/blink/renderer/platform/fonts/font_cache.h"
++#include "third_party/blink/renderer/platform/graphics/color.h"
+ #include "third_party/blink/renderer/platform/graphics/image.h"
+ #include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
+ #include "third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h"
+@@ -1763,6 +1764,14 @@ void WebView::ApplyWebPreferences(const web_pref::WebPreferences& prefs,
+ 
+   RuntimeEnabledFeatures::SetTranslateServiceEnabled(
+       prefs.translate_service_available);
++
++  SkColor color = SK_ColorTRANSPARENT;
++  if (!prefs.guest_instance_id) {  // not inside electron <webview /> tag, which is always transparent.
++    Color blink_color;
++    if (blink_color.SetFromString(WebString::FromASCII(prefs.background_color)))
++      color = static_cast<SkColor>(blink_color);
++  }
++  web_view->SetBaseBackgroundColor(color);
+ }
+ 
+ void WebViewImpl::ThemeChanged() {

+ 16 - 1
shell/browser/api/electron_api_web_contents.cc

@@ -1057,6 +1057,16 @@ void WebContents::AddNewContents(
   v8::HandleScope handle_scope(isolate);
   auto api_web_contents =
       CreateAndTake(isolate, std::move(new_contents), Type::kBrowserWindow);
+
+  // We call RenderFrameCreated here as at this point the empty "about:blank"
+  // render frame has already been created.  If the window never navigates again
+  // RenderFrameCreated won't be called and certain prefs like
+  // "kBackgroundColor" will not be applied.
+  auto* frame = api_web_contents->MainFrame();
+  if (frame) {
+    api_web_contents->HandleNewRenderFrame(frame);
+  }
+
   if (Emit("-add-new-contents", api_web_contents, disposition, user_gesture,
            initial_rect.x(), initial_rect.y(), initial_rect.width(),
            initial_rect.height(), tracker->url, tracker->frame_name,
@@ -1346,7 +1356,7 @@ void WebContents::BeforeUnloadFired(bool proceed,
   // there are two virtual functions named BeforeUnloadFired.
 }
 
-void WebContents::RenderFrameCreated(
+void WebContents::HandleNewRenderFrame(
     content::RenderFrameHost* render_frame_host) {
   auto* rwhv = render_frame_host->GetView();
   if (!rwhv)
@@ -1375,6 +1385,11 @@ void WebContents::RenderFrameCreated(
   WebFrameMain::RenderFrameCreated(render_frame_host);
 }
 
+void WebContents::RenderFrameCreated(
+    content::RenderFrameHost* render_frame_host) {
+  HandleNewRenderFrame(render_frame_host);
+}
+
 void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) {
   // This event is necessary for tracking any states with respect to
   // intermediate render view hosts aka speculative render view hosts. Currently

+ 1 - 0
shell/browser/api/electron_api_web_contents.h

@@ -196,6 +196,7 @@ class WebContents : public gin::Wrappable<WebContents>,
   void IncrementCapturerCount(gin::Arguments* args);
   void DecrementCapturerCount(gin::Arguments* args);
   bool IsBeingCaptured();
+  void HandleNewRenderFrame(content::RenderFrameHost* render_frame_host);
 
 #if BUILDFLAG(ENABLE_PRINTING)
   void OnGetDefaultPrinter(base::Value print_settings,

+ 0 - 16
shell/renderer/renderer_client_base.cc

@@ -253,22 +253,6 @@ void RendererClientBase::RenderFrameCreated(
   // DidCreateDocumentElement event.
   new ElectronApiServiceImpl(render_frame, this);
 
-  content::RenderView* render_view = render_frame->GetRenderView();
-  if (render_frame->IsMainFrame() && render_view) {
-    blink::WebView* webview = render_view->GetWebView();
-    if (webview) {
-      auto prefs = render_frame->GetBlinkPreferences();
-      if (prefs.guest_instance_id) {  // webview.
-        webview->SetBaseBackgroundColor(SK_ColorTRANSPARENT);
-      } else {  // normal window.
-        std::string name = prefs.background_color;
-        SkColor color =
-            name.empty() ? SK_ColorTRANSPARENT : ParseHexColor(name);
-        webview->SetBaseBackgroundColor(color);
-      }
-    }
-  }
-
 #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
   auto* dispatcher = extensions_renderer_client_->GetDispatcher();
   // ExtensionFrameHelper destroys itself when the RenderFrame is destroyed.